Appdesigner Gui issue code

18 views (last 30 days)
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 Comments
Franck paulin Ludovig pehn Mayo
@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.
Franck paulin Ludovig pehn Mayo
@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

Sign in to comment.

Accepted Answer

Adam Danz
Adam Danz on 29 Dec 2021
Edited: Adam Danz on 29 Dec 2021
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 Comments
Franck paulin Ludovig pehn Mayo
@Adam Danz actually it is a master project and there are still lot to do and add. Thank you for everything
dpb
dpb on 30 Dec 2021
Edited: dpb on 31 Dec 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.

Sign in to comment.

More Answers (0)

Categories

Find more on Develop Apps Using App Designer in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!