Hello everyone,
i need help concerning a Gui. Basically, İ am running 4 haptic motors at the same time, when the mouse cursor is in the ''band area'' ,the motor are effectively running and is supposed to stop running when it is out of the ''band area''. (When the cursor is in the band area,the ''band area'' becomes green and when it is outside the ''band area'' it turns red and should stop vibrating).
The problem i am facing is that even when it is outside the area it keeps vibrating continuosly. The motor works perfectly since i can stop them and make them run when using arduıno andmatlab script.When you go through the code , i wrote in capital letter THIS IS THE LINE THAT İS SUPPOSED TO STOP İT (IT is in two places and refers to the code).
Attached is a screenshot of the Gui.
properties (Access = public)
arduinoObj % Description
message
end
properties (Access = public)
T % Description
end
properties (Access = public)
region1
%
v_thick1 % Description
v_thick2 % Description
h_thick1 % Description
h_thick2 % Description
v_thickness_1
v_thickness_2
h_thickness_1
h_thickness_2
v_or_h_array
v_or_h
amplitude_array
exp_counter
end
properties (Access = public)
amplitude % Description
end
methods (Access = private)
function mycallback(app,src,event)
display(event.SelectedOption);
end
end
function startupFcn(app)
clc
% Read experiment data from a CSV file
% Plot patch on uiaxes
hold(app.UIAxes, 'on')
% region1 = patch(app.UIAxes,[-10 10 10 -10],[-5 -5 -4.4 -4.4],'r','FaceAlpha',1,...
%'LineWidth',0.01,'LineStyle','-','tag','region1');
load_folder = "C:\Users\student\Desktop\FRANCK\thesis\excel_data\";
load_name = "excel_data.xlsx";
load_addr = load_folder + load_name;
app.T = readtable(load_addr,'NumHeaderLines',1);
app.exp_counter = 1;
app.v_thickness_1 = app.T.Var1;
app.v_thickness_2 = app.T.Var2;
app.h_thickness_1 = app.T.Var3;
app.h_thickness_2 = app.T.Var4;
app.amplitude_array = app.T.Var5;
app.v_or_h_array = app.T.Var6;
app.v_thick1 = app.v_thickness_1(app.exp_counter);
app.v_thick2 = app.v_thickness_2(app.exp_counter);
app.h_thick1 = app.h_thickness_1(app.exp_counter);
app.h_thick2 = app.h_thickness_2(app.exp_counter);
app.v_or_h = app.v_or_h_array(app.exp_counter);
%Vertical line
if app.v_or_h == 0
app.region1 = patch(app.UIAxes, ...
[app.v_thick1 app.v_thick2 app.v_thick2 app.v_thick1], ...
[-10 -10 10 10],'r', ...
'FaceAlpha',1,...
'LineWidth',0.01, ...
'LineStyle','-','tag','region1');
%Horizontal line
elseif app.v_or_h == 1
app.region1 = patch(app.UIAxes,[-10 10 10 -10], ...
[app.h_thick1 app.h_thick1 app.h_thick2 app.h_thick2], ...
'r','FaceAlpha',1,...
'LineWidth',0.01, ...
'LineStyle','-','tag','region1');
end
% Define pointer behavior for patch
pm.enterFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'in');
pm.exitFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'out');
pm.traverseFcn = [];
iptSetPointerBehavior(app.region1, pm)
% Enable pointer manager for app
iptPointerManager(app.UIFigure,'enable');
% Create the Arduino serial object
app.arduinoObj = serialport("COM3", 9600);
configureTerminator(app.arduinoObj,"CR/LF");
%flush(app.arduinoObj);
%
for i=1:8
app.message = readline(app.arduinoObj);
disp(app.message)
end
function cursorPositionFeedback(app, hobj, inout)
% When inout is 'in', change hobj facecolor to green and update textbox.
% When inout is 'out' change hobj facecolor to red, and clear textbox.
% Check tag property of hobj to identify the object.
switch lower(inout)
case 'in'
facecolor = 'g';
txt = 'Motor(s) vibrating';
pointer = 'fleur';
writeline(app.arduinoObj, "4&MOTOR_1_2&0!");
% message = readline(app.arduinoObj);
% disp(message)
case 'out'
facecolor = 'r';
txt = 'No';
pointer = 'crosshair';
writeline(app.arduinoObj, "0&NO_MOTOR&0!"); %% THIS IS THE LINE THAT İS SUPPOSED TO STOP İT
% message = readline(app.arduinoObj);
% disp(message)
end
hobj.FaceColor = facecolor;
app.TextAreaEditField.Value = txt;
set(app.UIFigure, 'Pointer', pointer)
end
% Determine if mouse is within uiaxes
cp = app.UIFigure.CurrentPoint;
isInAxes = cp(1) >= app.UIAxes.Position(1) && ...
cp(1) <= sum(app.UIAxes.Position([1,3])) && ...
cp(2) >= app.UIAxes.Position(2) && ...
cp(2) <= sum(app.UIAxes.Position([2,4]));
if isInAxes
set(app.CurrentPositionEditField, 'Value',...
sprintf('%.2f, %.2f', app.UIAxes.CurrentPoint(1,1:2)))
else
set(app.CurrentPositionEditField, 'Value', '')
end
function NEXTButton_2Pushed(app, event)
uiconfirm(app.UIFigure,'Are You sure?','Confirm Close',...
'CloseFcn',@(src,event)mycallback(app,src,event));
app.exp_counter = app.exp_counter + 1;
app.v_or_h = app.v_or_h_array(app.exp_counter);
if ishandle(app.region1)
delete(app.region1);
end
%Vertical line
if app.v_or_h == 0
app.region1 = patch(app.UIAxes,...
[app.v_thick1 app.v_thick2 app.v_thick2 app.v_thick1],...
[-10 -10 10 10],'r',...
'FaceAlpha',1,...
'LineWidth',0.01,...
'LineStyle','-','tag','region1');
%Horizontal line
elseif app.v_or_h == 1
app.region1 = patch(app.UIAxes,[-10 10 10 -10],...
[app.h_thick1 app.h_thick1 app.h_thick2 app.h_thick2],...
'r','FaceAlpha',1,...
'LineWidth',0.01,...
'LineStyle','-','tag','region1');
end
% Define pointer behavior for patch
pm.enterFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'in');
pm.exitFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'out');
pm.traverseFcn = [];
iptSetPointerBehavior(app.region1, pm);
% Enable pointer manager for app
iptPointerManager(app.UIFigure,'enable');
% Create the Arduino serial object
%app.arduinoObj = serialport("COM6", 9600);
%configureTerminator(app.arduinoObj,"CR/LF");
%flush(app.arduinoObj);
%
for i=1:8
app.message = readline(app.arduinoObj);
disp(app.message)
end
function cursorPositionFeedback(app, hobj, inout)
% When inout is 'in', change hobj facecolor to green and update textbox.
% When inout is 'out' change hobj facecolor to red, and clear textbox.
% Check tag property of hobj to identify the object.
switch lower(inout)
case 'in'
facecolor = 'g';
txt = 'Motor(s) vibrating';
pointer = 'fleur';
writeline(app.arduinoObj, "4&MOTOR_1_2&0!");
% message = readline(app.arduinoObj);
% disp(message)
case 'out'
facecolor = 'r';
txt = 'No';
pointer = 'crosshair';
writeline(app.arduinoObj, "0&NO_MOTOR&0!"); %% THIS IS THE LINE THAT İS SUPPOSED TO STOP İT
% message = readline(app.arduinoObj);
% disp(message)
end
hobj.FaceColor = facecolor;
app.TextAreaEditField.Value = txt;
set(app.UIFigure, 'Pointer', pointer)
end

28 Kommentare

@Franck paulin Ludovig pehn Mayo - does the band turn red when the cursor moves outside the ''band area'' and so just the motor doesn't stop? I'm just wondering which part of
case 'out'
facecolor = 'r';
txt = 'No';
pointer = 'crosshair';
writeline(app.arduinoObj, "0&NO_MOTOR&0!");
is working..or does none of it work?
Franck paulin Ludovig pehn Mayo
Bearbeitet: Franck paulin Ludovig pehn Mayo am 21 Dez. 2021
@Geoff Hayes Thank you for replying me. Yes, the band turns red when the cursor moves outside the ''band area''. It is perfectly working without any issue.
It is quite a headache to me because , i can run and control the motor through matlab with the same code. But when using appdesigner , the motors runs and the band area turns green as soon as i move the cursor in but after that turns red but keep running even though it is outside the band area.
That is the issue. I dont know if i need a case or something else
@Franck paulin Ludovig pehn Mayo - how wide is the "band area"? Are you waiting for a few seconds of it being green before moving the cursor out of this area? Since the band area turns red and (presumably) the cursor is changing too, then the correct code is being executed. But the line
writeline(app.arduinoObj, "0&NO_MOTOR&0!");
doesn't seem to be doing anything. This could be because there is a message error (I don't know the appropriate/correct messages to use) or because it is being called too soon after the start is being called. That is why I'm wondering if you need to wait for a few seconds (while green) before moving the cursor away.
@Geoff Hayes There is a set of ''band areas" that are loaded from excel when clicking on the ''Next button". The band changes in size and becomes bigger and still facing the same issue.
No, I am not waiting for any second.
To summarize my project, I am going to use some subjects that are going to be blindfolded. On an electrovibration screen, the subject will use his finger (Haptic ring with 4 motors inside that plays the role of the cursor) and navigate on the electrovibration screen. The aim is that while navigating on the screen, I will project the first band area and when his finger will go in the band area, all the four motors should vibrate and stop vibrating when he is out...(So i cannot afford to run a code that should take into consideration some waiting time).
What is paradoxal to me is that , that same code that is not working on appdesigner is perfectly working matlab script while doing the text same on arduino.
Geoff Hayes
Geoff Hayes am 21 Dez. 2021
@Franck paulin Ludovig pehn Mayo I think you should try to wait a couple of seconds to see what happens. Or, if you could temporarily add a button to start and stop the motors respectively, that might be interesting to see if that functionality works from within app designer. If it does, then we can try to see why it might not work when moving the cursor.
@Geoff Hayes i will try that i come back to you. Thank you
@Geoff Hayes i have created two buttons (a start and a stop button).
The start button is working effectively but the stop button is still not working.(When i press the push button it is vibrating but then when i press the stop button it is not still vibrating. This basically is the entire code. (THİS İS WİTHİN APPDESİGNER).
Outside appdesigner the code is working without issue.
properties (Access = private)
arduinoObj
message
end
% Button pushed function: StartButton
function StartButtonPushed(app, event)
writeline(app.arduinoObj, "4&MOTOR_1_2_3_4&0!");
end
% Button pushed function: StopButton
function StopButtonPushed(app, event)
writeline(app.arduinoObj, "0&NO_MOTOR&0!");
end
@Franck paulin Ludovig pehn Mayo - it isn't clear to me why the line
writeline(app.arduinoObj, "0&NO_MOTOR&0!");
isn't doing what it should be doing. Are there any errors in the console window? Presumably it is being called
dpb
dpb am 22 Dez. 2021
Bearbeitet: dpb am 23 Dez. 2021
See what happens if you put a call to the external function(s) that work inside the AppDesigner callback functions instead of the commands themselves.
Ths would somehow seem to be an issue with callbacks and event queues and the like...
You might also just see if adding a
drawnow
function call after the call to writeline
@Geoff Hayes there is no errors in the window line.Yes, it is being called. I even try to display a message after the stop push button and it is working but the motors cannot stop vibrating
@dpb the drawnow unfortunately is not making any changes. I am not getting the first thing you said correctly please would you mind rephrasing it ...
Geoff Hayes
Geoff Hayes am 23 Dez. 2021
@Franck paulin Ludovig pehn Mayo - can you show us the line of code that stops the motors when called outside of the GUI (i.e. the line of code that works to stop the motors)? So that we can compare the two.
@Geoff Hayes It is the same code .I am using the same code outside and within the GUI.That is why i dont understand why it is not working.
Concerning the two buttons, do you think a state button is better than a push button? I have even tried to code it, but still no solution or i am coding it wrong.(Talking about the state button). I am still facing the same issue.
dpb
dpb am 23 Dez. 2021
I'm suggesting
% Button pushed function: StopButton
function StopButtonPushed(app, event)
motor=app.arduinoObj;
StopMotor(motor);
end
where StopMotor is your test function outside the GUI.
I don't know anything about the addressing/communications with the Arduino, I'd guess somehow the reference to the actual pin/device/whatever isn't right, but I don't have any insight as to just why/how/what that might be.
The idea is that if you can write a StartMotor and StopMotor function and execute them correctly standalone, then if you call those two routines themselves, they certainly should also work from the GUI. I know you you have tried the the equivalent from command line, but this just proves it conclusively with ML function code.
function stop_Motor(arduinoObj)
writeline(arduinoObj, "0&MOTOR_1_2_3_4&0!");
% message = readline(arduinoObj);
% disp(message)
end
Franck paulin Ludovig pehn Mayo
Bearbeitet: Franck paulin Ludovig pehn Mayo am 28 Dez. 2021
Merry Xmas to you all and happy new year by anticıpation.İ finally found an alternative solution . The solution i did is instead of selecting no_motor and basically put the speed to zero(0).However another problem came up. It looks like i need a waiting time of 0.5- 1second(moving from the band area to outside) in order for the system to work properly. I mean when i keep moving fast without a waiting time the we still come back to problem 1 until ı go in slowly. Any solution on this please
Adam Danz
Adam Danz am 28 Dez. 2021
Hi @Franck paulin Ludovig pehn Mayo, I saw that you pointed me to this thread so I'm trying to catch up with the discussion.
It looks like a section of your code from your question is not within a function block which would cause an error that prevents the app from running. I'm refering to this section below,
% Determine if mouse is within uiaxes
cp = app.UIFigure.CurrentPoint;
isInAxes = cp(1) >= app.UIAxes.Position(1) && ...
cp(1) <= sum(app.UIAxes.Position([1,3])) && ...
cp(2) >= app.UIAxes.Position(2) && ...
cp(2) <= sum(app.UIAxes.Position([2,4]));
if isInAxes
set(app.CurrentPositionEditField, 'Value',...
sprintf('%.2f, %.2f', app.UIAxes.CurrentPoint(1,1:2)))
else
set(app.CurrentPositionEditField, 'Value', '')
end
I could be wrong, it's difficult to follow the structure of the code since proper indentation is not applied (ctrl A to select all, then ctrl i to indent).
Perhaps you could attach the mlapp file. I realize we can't run it as-is without additional files but we can work around that.
classdef showCurrentPointApp_test01 < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
NEXTButton_2 matlab.ui.control.Button
NOIDONTButton matlab.ui.control.Button
YESIFEELITButton matlab.ui.control.Button
TextAreaEditField matlab.ui.control.EditField
TextAreaEditFieldLabel matlab.ui.control.Label
STOPButton matlab.ui.control.Button
STARTButton matlab.ui.control.Button
CurrentPositionEditField matlab.ui.control.EditField
CurrentPositionEditFieldLabel matlab.ui.control.Label
UIAxes matlab.ui.control.UIAxes
end
properties (Access = public)
arduinoObj % Description
message
end
properties (Access = public)
T % Description
end
properties (Access = public)
region1
%
v_thick1 % Description
v_thick2 % Description
h_thick1 % Description
h_thick2 % Description
v_thickness_1
v_thickness_2
h_thickness_1
h_thickness_2
v_or_h_array
v_or_h
amplitude_array
exp_counter
end
properties (Access = public)
amplitude % Description
end
methods (Access = private)
function mycallback(app,src,event)
display(event.SelectedOption);
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
clc
% Read experiment data from a CSV file
% Plot patch on uiaxes
hold(app.UIAxes, 'on')
% region1 = patch(app.UIAxes,[-10 10 10 -10],[-5 -5 -4.4 -4.4],'r','FaceAlpha',1,...
%'LineWidth',0.01,'LineStyle','-','tag','region1');
load_folder = "C:\Users\Hp\Desktop\thesis\excel_data\";
load_name = "excel_data.xlsx";
load_addr = load_folder + load_name;
app.T = readtable(load_addr,'NumHeaderLines',1);
app.exp_counter = 1;
app.v_thickness_1 = app.T.Var1;
app.v_thickness_2 = app.T.Var2;
app.h_thickness_1 = app.T.Var3;
app.h_thickness_2 = app.T.Var4;
app.amplitude_array = app.T.Var5;
app.v_or_h_array = app.T.Var6;
app.v_thick1 = app.v_thickness_1(app.exp_counter);
app.v_thick2 = app.v_thickness_2(app.exp_counter);
app.h_thick1 = app.h_thickness_1(app.exp_counter);
app.h_thick2 = app.h_thickness_2(app.exp_counter);
app.v_or_h = app.v_or_h_array(app.exp_counter);
%Vertical line
if app.v_or_h == 0
app.region1 = patch(app.UIAxes, ...
[app.v_thick1 app.v_thick2 app.v_thick2 app.v_thick1], ...
[-10 -10 10 10],'r', ...
'FaceAlpha',1,...
'LineWidth',0.01, ...
'LineStyle','-','tag','region1');
%Horizontal line
elseif app.v_or_h == 1
app.region1 = patch(app.UIAxes,[-10 10 10 -10], ...
[app.h_thick1 app.h_thick1 app.h_thick2 app.h_thick2], ...
'r','FaceAlpha',1,...
'LineWidth',0.01, ...
'LineStyle','-','tag','region1');
end
% Define pointer behavior for patch
pm.enterFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'in');
pm.exitFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'out');
pm.traverseFcn = [];
iptSetPointerBehavior(app.region1, pm)
% Enable pointer manager for app
iptPointerManager(app.UIFigure,'enable');
% Create the Arduino serial object
app.arduinoObj = serialport("COM6", 9600);
configureTerminator(app.arduinoObj,"CR/LF");
%flush(app.arduinoObj);
%
for i=1:8
app.message = readline(app.arduinoObj);
disp(app.message)
end
function cursorPositionFeedback(app, hobj, inout)
% When inout is 'in', change hobj facecolor to green and update textbox.
% When inout is 'out' change hobj facecolor to red, and clear textbox.
% Check tag property of hobj to identify the object.
switch lower(inout)
case 'in'
facecolor = 'g';
txt = 'Motor(s) vibrating';
pointer = 'fleur';
writeline(app.arduinoObj, "4&MOTOR_1_2&0!");
% message = readline(app.arduinoObj);
% disp(message)
case 'out'
facecolor = 'r';
txt = 'No';
pointer = 'crosshair';
writeline(app.arduinoObj, "0&MOTOR_1_2_3_4&0!");
% message = readline(app.arduinoObj);
% disp(message)
end
hobj.FaceColor = facecolor;
app.TextAreaEditField.Value = txt;
set(app.UIFigure, 'Pointer', pointer)
end
end
% Window button motion function: UIFigure
function UIFigureWindowButtonMotion(app, event)
% Determine if mouse is within uiaxes
cp = app.UIFigure.CurrentPoint;
isInAxes = cp(1) >= app.UIAxes.Position(1) && ...
cp(1) <= sum(app.UIAxes.Position([1,3])) && ...
cp(2) >= app.UIAxes.Position(2) && ...
cp(2) <= sum(app.UIAxes.Position([2,4]));
if isInAxes
set(app.CurrentPositionEditField, 'Value',...
sprintf('%.2f, %.2f', app.UIAxes.CurrentPoint(1,1:2)))
else
set(app.CurrentPositionEditField, 'Value', '')
end
end
% Button pushed function: STARTButton
function STARTButtonPushed(app, event)
clear
clc
fileID = fopen('exp.txt','w');
t = timer('ExecutionMode', 'fixedRate', ...
'Period', 0.05, ...
'TasksToExecute', Inf, ...
'TimerFcn', @(~,~) fprintf(fileID,'(X, Y, time) = (%g, %g, %s)\n', get(0, 'PointerLocation'), datetime('now') ));
start(t);
%stop(t) %whenever we want to stop.
fclose(fileID);
end
% Button pushed function: STOPButton
function STOPButtonPushed(app, event)
clear
clc
fileID = fopen('exp.txt','w');
t = timer('ExecutionMode', 'fixedRate', ...
'Period', 0.05, ...
'TasksToExecute', Inf, ...
'TimerFcn', @(~,~) fprintf(fileID,'(X, Y, time) = (%g, %g, %s)\n', get(0, 'PointerLocation'), datetime('now') ));
%start(t);
stop(t) %whenever we want to stop.
fclose(fileID);
end
% Button pushed function: NEXTButton_2
function NEXTButton_2Pushed(app, event)
uiconfirm(app.UIFigure,'Are You sure?','Confirm Close',...
'CloseFcn',@(src,event)mycallback(app,src,event));
app.exp_counter = app.exp_counter + 1;
app.v_or_h = app.v_or_h_array(app.exp_counter);
app.v_thick1 = app.v_thickness_1(app.exp_counter);
app.v_thick2 = app.v_thickness_2(app.exp_counter);
app.h_thick1 = app.h_thickness_1(app.exp_counter);
app.h_thick2 = app.h_thickness_2(app.exp_counter);
if ishandle(app.region1)
delete(app.region1);
end
%Vertical line
if app.v_or_h == 0
app.region1 = patch(app.UIAxes,...
[app.v_thick1 app.v_thick2 app.v_thick2 app.v_thick1],...
[-10 -10 10 10],'r',...
'FaceAlpha',1,...
'LineWidth',0.01,...
'LineStyle','-','tag','region1');
%Horizontal line
elseif app.v_or_h == 1
app.region1 = patch(app.UIAxes,[-10 10 10 -10],...
[app.h_thick1 app.h_thick1 app.h_thick2 app.h_thick2],...
'r','FaceAlpha',1,...
'LineWidth',0.01,...
'LineStyle','-','tag','region1');
end
% Define pointer behavior for patch
pm.enterFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'in');
pm.exitFcn = @(~,~) cursorPositionFeedback(app, app.region1, 'out');
pm.traverseFcn = [];
iptSetPointerBehavior(app.region1, pm)
% Enable pointer manager for app
iptPointerManager(app.UIFigure,'enable');
% Create the Arduino serial object
%app.arduinoObj = serialport("COM6", 9600);
%configureTerminator(app.arduinoObj,"CR/LF");
%flush(app.arduinoObj);
%
for i=1:8
app.message = readline(app.arduinoObj);
disp(app.message)
end
function cursorPositionFeedback(app, hobj, inout)
% When inout is 'in', change hobj facecolor to green and update textbox.
% When inout is 'out' change hobj facecolor to red, and clear textbox.
% Check tag property of hobj to identify the object.
switch lower(inout)
case 'in'
facecolor = 'g';
txt = 'Motor(s) vibrating';
pointer = 'fleur';
writeline(app.arduinoObj, "4&MOTOR_1_2_3_4&0!");
% message = readline(app.arduinoObj);
% disp(message)
case 'out'
facecolor = 'r';
txt = 'No';
pointer = 'crosshair';
writeline(app.arduinoObj, "0&MOTOR_1_2_3_4&0!");
% message = readline(app.arduinoObj);
% disp(message)
end
hobj.FaceColor = facecolor;
app.TextAreaEditField.Value = txt;
set(app.UIFigure, 'Pointer', pointer)
end
end
% Button pushed function: YESIFEELITButton
function YESIFEELITButtonPushed(app, event)
uiconfirm(app.UIFigure,'Are You sure?','Confirm Close',...
'CloseFcn',@(src,event)mycallback(app,src,event));
clear
clc
fileID = fopen('exp.txt2','a');
YES = "I FEEL IT";
fprintf(fileID,"%s\n",YES);
fclose(fileID);
end
% Button pushed function: NOIDONTButton
function NOIDONTButtonPushed(app, event)
uiconfirm(app.UIFigure,'Are You sure?','Confirm Close',...
'CloseFcn',@(src,event)mycallback(app,src,event));
clear
clc
fileID = fopen('exp.txt2','a');
NO = "I DON'T FEEL IT";
fprintf(fileID,"%s\n",NO);
fclose(fileID);
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 640 480];
app.UIFigure.Name = 'MATLAB App';
app.UIFigure.WindowButtonMotionFcn = createCallbackFcn(app, @UIFigureWindowButtonMotion, true);
% Create UIAxes
app.UIAxes = uiaxes(app.UIFigure);
xlabel(app.UIAxes, 'X')
ylabel(app.UIAxes, 'Y')
zlabel(app.UIAxes, 'Z')
app.UIAxes.XLim = [-10 10];
app.UIAxes.YLim = [-10 10];
app.UIAxes.Colormap = [0 0 0.515625;0 0 0.53125;0 0 0.546875;0 0 0.5625;0 0 0.578125;0 0 0.59375;0 0 0.609375;0 0 0.625;0 0 0.640625;0 0 0.65625;0 0 0.671875;0 0 0.6875;0 0 0.703125;0 0 0.71875;0 0 0.734375;0 0 0.75;0 0 0.765625;0 0 0.78125;0 0 0.796875;0 0 0.8125;0 0 0.828125;0 0 0.84375;0 0 0.859375;0 0 0.875;0 0 0.890625;0 0 0.90625;0 0 0.921875;0 0 0.9375;0 0 0.953125;0 0 0.96875;0 0 0.984375;0 0 1;0 0.015625 1;0 0.03125 1;0 0.046875 1;0 0.0625 1;0 0.078125 1;0 0.09375 1;0 0.109375 1;0 0.125 1;0 0.140625 1;0 0.15625 1;0 0.171875 1;0 0.1875 1;0 0.203125 1;0 0.21875 1;0 0.234375 1;0 0.25 1;0 0.265625 1;0 0.28125 1;0 0.296875 1;0 0.3125 1;0 0.328125 1;0 0.34375 1;0 0.359375 1;0 0.375 1;0 0.390625 1;0 0.40625 1;0 0.421875 1;0 0.4375 1;0 0.453125 1;0 0.46875 1;0 0.484375 1;0 0.5 1;0 0.515625 1;0 0.53125 1;0 0.546875 1;0 0.5625 1;0 0.578125 1;0 0.59375 1;0 0.609375 1;0 0.625 1;0 0.640625 1;0 0.65625 1;0 0.671875 1;0 0.6875 1;0 0.703125 1;0 0.71875 1;0 0.734375 1;0 0.75 1;0 0.765625 1;0 0.78125 1;0 0.796875 1;0 0.8125 1;0 0.828125 1;0 0.84375 1;0 0.859375 1;0 0.875 1;0 0.890625 1;0 0.90625 1;0 0.921875 1;0 0.9375 1;0 0.953125 1;0 0.96875 1;0 0.984375 1;0 1 1;0.015625 1 0.984375;0.03125 1 0.96875;0.046875 1 0.953125;0.0625 1 0.9375;0.078125 1 0.921875;0.09375 1 0.90625;0.109375 1 0.890625;0.125 1 0.875;0.140625 1 0.859375;0.15625 1 0.84375;0.171875 1 0.828125;0.1875 1 0.8125;0.203125 1 0.796875;0.21875 1 0.78125;0.234375 1 0.765625;0.25 1 0.75;0.265625 1 0.734375;0.28125 1 0.71875;0.296875 1 0.703125;0.3125 1 0.6875;0.328125 1 0.671875;0.34375 1 0.65625;0.359375 1 0.640625;0.375 1 0.625;0.390625 1 0.609375;0.40625 1 0.59375;0.421875 1 0.578125;0.4375 1 0.5625;0.453125 1 0.546875;0.46875 1 0.53125;0.484375 1 0.515625;0.5 1 0.5;0.515625 1 0.484375;0.53125 1 0.46875;0.546875 1 0.453125;0.5625 1 0.4375;0.578125 1 0.421875;0.59375 1 0.40625;0.609375 1 0.390625;0.625 1 0.375;0.640625 1 0.359375;0.65625 1 0.34375;0.671875 1 0.328125;0.6875 1 0.3125;0.703125 1 0.296875;0.71875 1 0.28125;0.734375 1 0.265625;0.75 1 0.25;0.765625 1 0.234375;0.78125 1 0.21875;0.796875 1 0.203125;0.8125 1 0.1875;0.828125 1 0.171875;0.84375 1 0.15625;0.859375 1 0.140625;0.875 1 0.125;0.890625 1 0.109375;0.90625 1 0.09375;0.921875 1 0.078125;0.9375 1 0.0625;0.953125 1 0.046875;0.96875 1 0.03125;0.984375 1 0.015625;1 1 0;1 0.984375 0;1 0.96875 0;1 0.953125 0;1 0.9375 0;1 0.921875 0;1 0.90625 0;1 0.890625 0;1 0.875 0;1 0.859375 0;1 0.84375 0;1 0.828125 0;1 0.8125 0;1 0.796875 0;1 0.78125 0;1 0.765625 0;1 0.75 0;1 0.734375 0;1 0.71875 0;1 0.703125 0;1 0.6875 0;1 0.671875 0;1 0.65625 0;1 0.640625 0;1 0.625 0;1 0.609375 0;1 0.59375 0;1 0.578125 0;1 0.5625 0;1 0.546875 0;1 0.53125 0;1 0.515625 0;1 0.5 0;1 0.484375 0;1 0.46875 0;1 0.453125 0;1 0.4375 0;1 0.421875 0;1 0.40625 0;1 0.390625 0;1 0.375 0;1 0.359375 0;1 0.34375 0;1 0.328125 0;1 0.3125 0;1 0.296875 0;1 0.28125 0;1 0.265625 0;1 0.25 0;1 0.234375 0;1 0.21875 0;1 0.203125 0;1 0.1875 0;1 0.171875 0;1 0.15625 0;1 0.140625 0;1 0.125 0;1 0.109375 0;1 0.09375 0;1 0.078125 0;1 0.0625 0;1 0.046875 0;1 0.03125 0;1 0.015625 0;1 0 0;0.984375 0 0;0.96875 0 0;0.953125 0 0;0.9375 0 0;0.921875 0 0;0.90625 0 0;0.890625 0 0;0.875 0 0;0.859375 0 0;0.84375 0 0;0.828125 0 0;0.8125 0 0;0.796875 0 0;0.78125 0 0;0.765625 0 0;0.75 0 0;0.734375 0 0;0.71875 0 0;0.703125 0 0;0.6875 0 0;0.671875 0 0;0.65625 0 0;0.640625 0 0;0.625 0 0;0.609375 0 0;0.59375 0 0;0.578125 0 0;0.5625 0 0;0.546875 0 0;0.53125 0 0;0.515625 0 0;0.5 0 0];
app.UIAxes.XTick = [-10 -8 -6 -4 -2 0 2 4 6 8 10];
app.UIAxes.YTick = [-10 -8 -6 -4 -2 0 2 4 6 8 10];
app.UIAxes.XGrid = 'on';
app.UIAxes.YGrid = 'on';
app.UIAxes.Position = [-44 1 571 480];
% Create CurrentPositionEditFieldLabel
app.CurrentPositionEditFieldLabel = uilabel(app.UIFigure);
app.CurrentPositionEditFieldLabel.FontSize = 14;
app.CurrentPositionEditFieldLabel.Position = [541 214 106 22];
app.CurrentPositionEditFieldLabel.Text = 'CurrentPosition';
% Create CurrentPositionEditField
app.CurrentPositionEditField = uieditfield(app.UIFigure, 'text');
app.CurrentPositionEditField.FontSize = 16;
app.CurrentPositionEditField.Position = [541 193 98 22];
% Create STARTButton
app.STARTButton = uibutton(app.UIFigure, 'push');
app.STARTButton.ButtonPushedFcn = createCallbackFcn(app, @STARTButtonPushed, true);
app.STARTButton.BackgroundColor = [0 1 0];
app.STARTButton.FontWeight = 'bold';
app.STARTButton.Position = [539 439 99 22];
app.STARTButton.Text = 'START';
% Create STOPButton
app.STOPButton = uibutton(app.UIFigure, 'push');
app.STOPButton.ButtonPushedFcn = createCallbackFcn(app, @STOPButtonPushed, true);
app.STOPButton.BackgroundColor = [1 0 0];
app.STOPButton.FontWeight = 'bold';
app.STOPButton.Position = [540 410 99 22];
app.STOPButton.Text = 'STOP';
% Create TextAreaEditFieldLabel
app.TextAreaEditFieldLabel = uilabel(app.UIFigure);
app.TextAreaEditFieldLabel.HorizontalAlignment = 'center';
app.TextAreaEditFieldLabel.VerticalAlignment = 'bottom';
app.TextAreaEditFieldLabel.FontSize = 16;
app.TextAreaEditFieldLabel.Position = [551 152 73 22];
app.TextAreaEditFieldLabel.Text = 'Text Area';
% Create TextAreaEditField
app.TextAreaEditField = uieditfield(app.UIFigure, 'text');
app.TextAreaEditField.FontSize = 16;
app.TextAreaEditField.Position = [546 124 92 24];
% Create YESIFEELITButton
app.YESIFEELITButton = uibutton(app.UIFigure, 'push');
app.YESIFEELITButton.ButtonPushedFcn = createCallbackFcn(app, @YESIFEELITButtonPushed, true);
app.YESIFEELITButton.FontName = 'Arial';
app.YESIFEELITButton.FontSize = 11;
app.YESIFEELITButton.Position = [539 359 100 22];
app.YESIFEELITButton.Text = 'YES, I FEEL IT';
% Create NOIDONTButton
app.NOIDONTButton = uibutton(app.UIFigure, 'push');
app.NOIDONTButton.ButtonPushedFcn = createCallbackFcn(app, @NOIDONTButtonPushed, true);
app.NOIDONTButton.Position = [541 328 97 22];
app.NOIDONTButton.Text = 'NO, I DON''T';
% Create NEXTButton_2
app.NEXTButton_2 = uibutton(app.UIFigure, 'push');
app.NEXTButton_2.ButtonPushedFcn = createCallbackFcn(app, @NEXTButton_2Pushed, true);
app.NEXTButton_2.BackgroundColor = [0.4941 0.1843 0.5569];
app.NEXTButton_2.FontColor = [1 1 1];
app.NEXTButton_2.Position = [540 293 100 22];
app.NEXTButton_2.Text = 'NEXT';
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = showCurrentPointApp_test01
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% Execute the startup function
runStartupFcn(app, @startupFcn)
if nargout == 0
clear app
end
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure)
end
end
end
Adam Danz
Adam Danz am 28 Dez. 2021
Franck, I read through the commentary above and tinkered with your app (commenting-out the arduino commands etc).
I understand that you have no problems when this is run in an m-file and my guess is that you're using regular figures in the m-file whereas apps use uifigures. Perhaps the pointer behavior has slightly longer processing delays in uifigures than regular figures and since the target is so narrow, the trigger caused by leaving the target is too soon after the trigger caused by entering the target.
If the use of uifigures is the cause, moving the cursorPositionFeedback function to an m-file will not fix the problem.
The first step I would take is to make a copy of the m-file script that contains the problem-free version and replace the regular figures with uifigures. If the problem occurs after that change, it supports this hypothesis. If the change to uifigures does not cause a problem in the script, it rules out this hypothesis.
Franck paulin Ludovig pehn Mayo
Bearbeitet: Franck paulin Ludovig pehn Mayo am 28 Dez. 2021
@Adam Danz Well,actually in the regular files I am not using any "graph". My aim there was just to run and stop the motors when needed through some codes and it works perfectly. So technically there's no "figure" when running the normal files. Now, coming to appdesigner the app needs some times (0.5 to 1second) to work perfectly. Unfortunately, I can't allow myself to have a waiting time. Furthermore, i would like to add something. Concerning the band area( when clicking on the next button , I will have other band areas with bigger sizes ; unfortunately it's still the same issue) I think the problem could be more about appdesigner...(I have even added drawnow) but still facing the same issue.
Geoff Hayes
Geoff Hayes am 29 Dez. 2021
@Franck paulin Ludovig pehn Mayo - I don't think the issue is with app designer, it is more how you are linking the starting and stopping of the motors to the movement/location of the cursor. As you have said above, the faster you move the cursor, the more likely you are to have an issue if there is no "waiting time". I don't think it is unreasonable to ignore these cursor events while the motors are starting or stopping. Of course, by doing this you may miss some events that you are actually interested in.
I suppose what you could do is for that short waiting period (while the motors are starting or stopping) show a progress indicator or waitbar...but I'm not sure if that will be enough as the user could move the cursor location outside of your bands. Unless you can some how stop the movement of the cursor or restore it to its original postion once the waiting period is over. But that might lead to other undesireable/confusing behaviour.
Adam Danz
Adam Danz am 29 Dez. 2021
Bearbeitet: Adam Danz am 29 Dez. 2021
Ok, in that case, I agree with Geoff Hayes that the problem is likely caused by the temporal asynchronies between cursor sampling and the control of the motors. As Geoff mentioned, adding a progress bar to stall execution briefly will not prevent the user from moving the cursor, it may also add additional delay, and it will interrupt any natural behavior that you may be trying to capture so I don't think that's a viable solution. I'll add an answer to demonstrate this point.
s pernot
s pernot am 2 Jan. 2022
Bearbeitet: Adam Danz am 2 Jan. 2022
hi frank
i would suggest to use the following trick from Y. Altman to better tune your GUI app callbacks
persistent lasttime
if isempty(lasttime)
lasttime = clock;
end % if lasttime
if all(clock - lasttime >= [0 0 0 0 0 0.04]) % 25 Hz refreshing
% do your stuff here
% xxxx
% update for next callback entry
lasttime = clock;
end
% exit callback as soon as possible here
several points :
  • clock is 50x more efficient on my PC than datetime('now')... so use it or alternatively use cputime instead of datetime('now')
  • callbacks keep being triggered so you must control the way they work and exit as soon as possible, you may also prevent reentry if necessary by using uiaxes Interactivity and BusyAction props or similar
  • you must tune the refreshing frequency in the callback to match your responsiveness
i hope this will help
happy new year
Adam Danz
Adam Danz am 2 Jan. 2022
Great suggestions, @s pernot. The first two points will definitely speed up the code but, depending on the specific hypothese being tested, the processing delay may still be insufficient.
Using an online cursor speed test, I clocked a mouse movement speed of 5,000 px/sec using moderate mouse control. Let's say the bar width is 20 pixels (from the OP's description, it could be narrower). At a constant 5k px/sec, the mouse crosses the bar in 4 milliseconds. So the duration of the vibration needs to be 4ms and the on/off delay should be much less than 4 ms or the entire vibration will be received after the mouse is outside of the bar region. This is assuming that the cursor sampling rate, display resolution, and DPI are all sufficient.
@s pernot thank you a lot. İ will try to implement it. İ was working on other aspects of my thesis project. İ am just seeing the replies now.
Under which callback should i put ıt? After both writeline commands?
the 'do your stuffs here' is where i have to write the 'Writeline (app...) right? İ am not getting the update thing
function cursorPositionFeedback(app, hobj, inout)
% When inout is 'in', change hobj facecolor to green and update textbox.
% When inout is 'out' change hobj facecolor to red, and clear textbox.
% Check tag property of hobj to identify the object.
switch lower(inout)
case 'in'
facecolor = 'g';
txt = 'Motor(s) vibrating';
pointer = 'fleur';
writeline(app.arduinoObj, "4&MOTOR_1_2_3_4&0!");
% message = readline(app.arduinoObj);
% disp(message)
case 'out'
facecolor = 'r';
txt = 'No';
pointer = 'crosshair';
writeline(app.arduinoObj, "0&MOTOR_1_2_3_4&0!");
% message = readline(app.arduinoObj);
% disp(message)
end
@Adam Danz The mouse cursor is actually someone's finger with a ring embedded with 4 motors.technically since it is a test, the 'subject' does not need to be that fast. The ideal dealy time for me is between half a second to 1 second thıs ıs where my GUİ is still responsive.
@s pernot thank you a lot. İ will try to implement it. İ was working on other aspects of my thesis project. İ am just seeing the replies now.
Under which callback should i put ıt? After both writeline commands?
the 'do your stuffs here' is where i have to write the 'Writeline (app...) right? İ am not getting the update thing

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

Adam Danz
Adam Danz am 29 Dez. 2021
Bearbeitet: Adam Danz am 29 Dez. 2021

1 Stimme

Demo 1: Show sampling interval
This simplified demo tracks the cursor position within the axes and adds a marker (.) to indicate the current cursor location every time the cursor is sampled. As you can see, the faster I move the mouse, the wider the spatial interval becomes between samples.
The demo also records and displays how much time was spend within the cyan/blue vertical band and you can see the number of cursor samples within the band every time the cursor crosses it. Naturally, the faster the cursor is moving, the less time is spent within the band. On the 4th and 6th crossing, the cursor is moving too quickly and the entrance/exit of the band isn't captured. It's probably the case that the temporal interval between turning on and off your motors has a lower limit that is not met during faster cursor movement.
If this is indeed the bottleneck, solutions include
  • Increase the width of the band
  • Limiting the speed of cursor motion
  • Use a different method of tracking mouse movement
I come from a neurophsyiology lab where I recorded responses from single neurons that can fire at intervals as low as 0.001 sec. Our eye tracking methods, control of stimuli, and data sampling therefore must all be sub-millisecond resolution. Matlab isn't built for this type of temporal demands so we rely on other custom software.
% Create figure with vertical band
app.UIFigure = uifigure();
app.uiax = uiaxes(app.UIFigure, 'Units','normalized','Position', [.1 .1 .8 .8]);
app.patch = patch(app.uiax,[.49 .51 .51 .49], [0 0 1 1], 'c');
xlim(app.uiax, [0,1])
ylim(app.uiax, [0,1])
hold(app.uiax,'on')
app.UIFigure.WindowButtonMotionFcn = {@WindowButtonMotion, app.uiax};
% Control cursor behavior when entering/exiting band
pm.enterFcn = @(~,~) cursorPositionFeedback(app, app.patch, 'in');
pm.exitFcn = @(~,~) cursorPositionFeedback(app, app.patch, 'out');
pm.traverseFcn = [];
iptSetPointerBehavior(app.patch, pm)
iptPointerManager(app.UIFigure,'enable');
function cursorPositionFeedback(app, hobj, inout)
% Responds to cursor entering/exiting vertical band
persistent timein
switch inout
case 'in'
hobj.FaceColor = 'b';
timein = datetime('now');
case 'out'
hobj.FaceColor = 'c';
timeInPatch = seconds(datetime('now')-timein);
ax = ancestor(hobj, 'axes');
cp = ax.CurrentPoint;
text(ax, 0.52, cp(1,2), sprintf('%.3f sec.', timeInPatch), ...
'HorizontalAlignment','Left', ...
'VerticalAlignment','bottom', ...
'FontSize', 12, ...
'FontWeight', 'bold', ...
'Color', 'b')
end
end
function WindowButtonMotion(uifig, event, ax)
% Responds to cursor moving in figure window.
cp = ax.CurrentPoint;
isInAxes = cp(1,1) >= ax.XLim(1) && ...
cp(1,1) <= ax.XLim(2) && ...
cp(1,2) >= ax.YLim(1) && ...
cp(1,2) <= ax.YLim(2);
if isInAxes
plot(ax, cp(1,1), cp(1,2), 'k.')
end
end
Demo 2: What is the minimum sampling interval?
In this demo, the user can pass through the band many times to collect a bunch of durations of time measured within the band as quickly as possible. Each duration is recorded in the lower axes. If the pass-through is too fast, it is not detected nor recorded. After creating the data, press the analysis button to reveal the minimum duration which is an estimate of the lower bound to the sampling interval given the width of the band. For my test, it results in 0.062 seconds or 62 ms.
% Create figure with vertical band
app.UIFigure = uifigure();
app.uiax = uiaxes(app.UIFigure, 'Units','normalized','Position', [.05 .55 .9 .4]);
app.uiax2 = uiaxes(app.UIFigure, 'Units','normalized','Position', [.05 .05 .9 .4]);
app.patch = patch(app.uiax,[.49 .51 .51 .49], [0 0 1 1], 'c');
app.button = uibutton(app.UIFigure, 'push', 'position', [50 190 80 30], ...
'Text', 'Analyze', 'ButtonPushedFcn', {@analyzeDurations,app});
xlim(app.uiax, [0,1])
ylim(app.uiax, [0,1])
hold(app.uiax,'on')
hold(app.uiax2, 'on')
app.UIFigure.WindowButtonMotionFcn = @WindowButtonMotion;
% Control cursor behavior when entering/exiting band
pm.enterFcn = @(~,~) cursorPositionFeedback(app, app.patch, 'in');
pm.exitFcn = @(~,~) cursorPositionFeedback(app, app.patch, 'out');
pm.traverseFcn = [];
iptSetPointerBehavior(app.patch, pm)
iptPointerManager(app.UIFigure,'enable');
function cursorPositionFeedback(app, hobj, inout)
% Responds to cursor entering/exiting vertical band
persistent timein count
if isempty(count) || isempty(app.uiax2.Children)
count = 0;
end
switch inout
case 'in'
hobj.FaceColor = 'b';
timein = datetime('now');
case 'out'
hobj.FaceColor = 'c';
count = count + 1;
timeInPatch = seconds(datetime('now')-timein);
stem(app.uiax2, count, timeInPatch, 'b-')
end
drawnow()
end
function analyzeDurations(~, ~, app)
% display minimum duration
data = cell2mat(get(app.uiax2.Children, 'YData'));
yline(app.uiax2, min(data), 'r-', 'LineWidth', 1)
title(app.uiax2, sprintf('Min duration: %.3f sec', min(data)))
end
function WindowButtonMotion(~, ~)
end

9 Kommentare

@Adam Danz @Geoff Hayes @dpb Thank you all for your great inputs ,i am learning new things along the line.
If this is indeed the bottleneck, solutions include
  • Increase the width of the band
  • Limiting the speed of cursor motion
  • Use a different method of tracking mouse movement.
a) Increase the width of the band.
My project is about finding the minimum threshold a subject can feel the vibration and/or difference when the cursor in on the band. The experiment is done on an electrovibration screen as well.
By clicking on the next button, the width band is increased everytime one's clicks on it.
b) Limiting the speed of cursor motion
Unfurtunately, it is not up to me since every subject doing the experiment is going to be blindfolded and will be moving the cursor according to their instinct.So this alternative cannot work.
3) Use a different method of tracking mouse movement.
Do you have a suugestion for me please? I mean another code related to this .I think the third point is the one that i can go with.
Adam Danz
Adam Danz am 30 Dez. 2021
I'm suggesting to use different software that has better temporal precision. I'm sure similar studies have been done to measure vibration detection thresholds so I would start by finding half a dozen frequently cited papers on this topic and I would study their methods sections. My guess is that customized software using C++ is commonly used.
Franck paulin Ludovig pehn Mayo
Bearbeitet: Franck paulin Ludovig pehn Mayo am 30 Dez. 2021
@Adam Danz so i guess there is no solution possible concerning matlab. I have been working on this for quite long and the time is playing against me and there is still a little bit lot to do. Do you think that Guide is faster that appdesigner?
The only software i can have a try with is Python. I know a little bit of python. Nothing garanties me it is faster than matlab. I nevertheless appreciate all the effort and if something comes your mind please let me know.
Adam Danz
Adam Danz am 30 Dez. 2021
Unfortunately I don't know enough about the hardware and how Matlab samples the cursor etc to offer more advice. Another area of concern is the delay between the user crossing the bar and receiving the tactile feedback. If you look at the first GIF in my answer, you'll see a very large delay between the cursor position and the appearance of black points that sample the cursor positions. Some of that time is spent generating graphics which, in your case, that time would be spent sending the signal to arduino and creating the vibration. Nevertheless, this gap is gigantic in terms of sensory processing. So even if the vibrations turned on/off those events would likely be delayed from the actual entrance/exit from the bar.
My experiments in neurophysiology faced similar challenges. Neurons can fire up to 1000 times per second so data had to be collected at millisecond resolution and the visual stimulus had to be syncronized to the data collection rate at ms resolution as well so we can infer the visual input that led to each neural response. Furthermore, we were tracking the eye position of the monkeys which also had to be in sync at the same temporal intervals. This could not be done in Matlab - I wouldn't even try it. The stimuli were generated with OpenGL and the data collection was run by software custom built in C. This is much faster and avoids the overhead inherent in Matlab's graphics and interactions tools.
Franck paulin Ludovig pehn Mayo
Bearbeitet: Franck paulin Ludovig pehn Mayo am 30 Dez. 2021
@Adam Danz spending months on a project and thinking about switching platform and software.Smh.
I would like to know if it is possible that i could use your ''software custom build C'' and open Gl data as a base in other to start mine. If it is not possible i will understand. Thank you very much for your support. Nevertheless, I have learned a lot
dpb
dpb am 30 Dez. 2021
I agree w/ @Adam Danz -- the kind of time resolution you need here simply cannot be done with high-level MATLAB code -- it simply isn't the kind of thing MATLAB was intended for -- nor was Windows on top of which MATLAB runs.
The only possible way I would see you could possibly salvage some of what you have done would be to move all the hardware stuff into mex code but even then with my (extremely limited) understanding of the Arduino interface as a serial communications port other than for code downloaded and run wholly on the Arduino, I'd guess the latency there alone is more than your expected results time resolution would need to be to be able to draw any real conclusions.
But, the high-level MATLAB graphics and the Windows/MATLAB GUI interactions are going to be 10s if not 100s of msec and occasionally when Windows task switches on you behind your back that you can't control, it may well approach 1000 ms.
ML is just not a real-time system for anything other than glacially-slow "real" time applications.
Adam Danz
Adam Danz am 30 Dez. 2021
@Franck paulin Ludovig pehn Mayo, I feel your pain. Even though you've already invested lots of time into something that probably won't work, you haven't used this to collect data yet so it could have been a lot worse. Suppose you never had the original error you reported and never realized there were processing delays etc. You could have spent time searching for subjects, collecting data, analyzing it, etc before you realized there was a delay problem or, worse yet, you may have never realized it and your results may have been bogus. I know someone who collected data nearly every workday for 4 years before discovering a programming flaw that affected all of the data.
About the custom software from my lab; it's not something you could use as a base. It's much more complex and runs over 4 machines in a Client/Server/Master/Slave setup. It has been developed in piecemeal over 20 years by lots of different people and I only wrote parts of it so it's not really mine to give away.
I don't know whether this is an undergrad project, a major study for publication, or something in between, so I'm hesitent to give more advice. But if this were my project I'd spend a lot of time reading methods sections of similar papers and noting the software and hardware they used. Sometimes authors will give you their code if you ask for it (sometimes journals require it). Alternatively, depending on the purpose of the experiment, you could rethink the question you're asking and restrict it to the capabilities of Matlab.
@Adam Danz actually it is a master project and there are still lot to do and add. Thank you for everything
dpb
dpb am 30 Dez. 2021
Bearbeitet: dpb am 31 Dez. 2021
@Franck paulin Ludovig pehn Mayo -- I also feel your pain. Besides Adam's suggestion to research similar projects for ideas on how others have accomplished a similar test, I'd say it's time for a serious face-to-face with your thesis advisor on just what it is that is being expected/reqyured to be done here to get you your degree.
If this work is being supported all or in part by some research grant for which he/she is the PI, then they've got the responsibility to ensure you have the tools to meet the objectives of the research grant as outlined in the proposal. If it is simply an internal project, then that is something else again.
Like Adam, I've also run into cases where "things happened" and either experimental data were, as in his case, questionable or worthless, or a particular case where the results of a computer simulation were sufficiently in error so as to make the project unusable until the model was corrected, all the simulations rerun and the report conclusions revised to match. Fortunately in that particular case, the funder of the research and the university were flexible-enough and it was clear what was wrong/how to fix the code that they let him go ahead and graduate on time and submit the revisions to the thesis later.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Develop Apps Using App Designer finden Sie in Hilfe-Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by