Logical Calculation Error in GUI plotting

2 views (last 30 days)
I am having issues with a GUI program I wrote using GUIDE that measures pressure of a chamber (denoted as P1 in code) in terms of the variable input pressure (denoted as Pin in code) and time (implemented as a non-stop timer object). It uses a for-loop to run through the timer object, using the time step as increments for each P1 increase/decrease.
What works: So far the GUI is able to run through the program smoothly. It evaluates P1 through the for loop and uses the if/else statements to go through the correct pressure conditions. The GUI is able to plot a dynamic plot with a curve profile while allowing the user to adjust the input pressure as the program is running.
The problem: (1) Assuming that the pressure equations are correct (they should be correct), there seems to be a logical calculation error in the for-loop (its the only command that goes through the calculations). As the GUI runs, P1 will start out nicely, gradually increasing when Pin is always greater than P1. However once P1 is able to reach it max possible value (max value of approximately 2), P1 will always equal to Pin, no matter much you increase or decrease Pin. It is like it's "calculating too fast". P1 is suppose to always slowly increase/decrease as the user adjust the slider. (2) There is also a problem where the program seems to always skip over the last "else" statement. When the difference in between Pin and P1 is largely negative, P1 should not change at all. For example, when the plot is settle at max values, changing Pin from 2 to 0 immediately should trigger the last else condition, yet P1 will immediately follow Pin.
How would I be able to solve the logical error? Instead of for-loops should I use another function to call this callback function?
All of my important calculations are done code shown below. I also attached the GUI .m and .fig files for convenience.
There are many of specifics for this problem so if anyone trying to help get confused, feel free to ask me questions for clarification
%code
function user_timercallback(obj,event,hObject)
handles=guidata(hObject);
handles.t=handles.t+0.01;
% Initial Conditions
Pin = get(handles.slider1,'value'); % Input Pressure (Pa)
% Controlled by User via slider
P1 = 0; % Initial Pressure 1 (Pa)
r0 = 0.0254; % Initial chamber radius (m)
dP1_shutoff = 1.2; % Shutoff Pressure (Pa)
Rst = 1; % Flow Resistance
V1 = (4/3)*pi*r0^3; % Initial Volume (m^3)
% Ideal Gas Law Variables
dn = 0.00000001; % moles/sec
R = 8.3145; % J/(mol K)
T = 293.15; % Room Temperature (K) = 20 C
dt = 0.001; % delta t
% Calculation of Pressure 1 with constant volume
for t=0:dt:handles.t
if -dP1_shutoff < Pin - P1 && Pin > P1
P1 = P1 + (dn.*dt.*R*T)./V1;
elseif -dP1_shutoff < Pin - P1 && Pin < P1
P1 = P1 + (-dn.*dt.*R*T)./V1;
else
P1 = P1; % + (0.*dt.*R*T)./V1;
end
end
% Calculation of Pressure 1 with varying volume
% for t=0:0.01:handles.t;
% if -dP1_shutoff < Pin - P1
% Vdot = (Pin - P1)./R;
% else
% Vdot = 0;
% end
%
% V1 = V1 + Vdot*t; % Updated volume of the chamber
% r = ((3./(4.*pi)).*V1).^(1./3); % Updated radius of the chamber
% P1 = 2*[1./(r0.^2.*r)].*[1-(r0./r).^6] % Updated Pressure 1
% end
% Stores data for Input Pressure
Pin_xdata = [get(handles.Pin_signal, 'XData') t];
Pin_ydata = [get(handles.Pin_signal, 'YData') Pin];
% Stores data for Pressure 1
P1_xdata = [get(handles.P1_signal, 'XData') t];
P1_ydata = [get(handles.P1_signal, 'YData') P1];
% Configuring Pin Plot
set(handles.Pin_axes,'xlim',[0 handles.t]);
set(handles.Pin_signal,'xdata',Pin_xdata,'ydata',Pin_ydata);
set(handles.Pin_dot,'xdata',t(end),'ydata',Pin(end));
% Configuring P1 Plot
set(handles.P1_axes,'xlim',[0 handles.t]);
set(handles.P1_signal,'xdata',P1_xdata,'ydata',P1_ydata);
set(handles.P1_dot,'xdata',t(end),'ydata',P1(end));
guidata(hObject,handles);

Accepted Answer

Geoff Hayes
Geoff Hayes on 16 Apr 2016
Gary - the problem could be that you have a timer firing every 0.01 seconds (or close to that because this isn't guaranteed especially as your callback does a fair amount of work in processing and displaying data) and your callback starts the pressure P1 always initialized to zero and you have a for loop that always begins with t initialized to zero which you iterate (in steps of 0.0001 up to handles.t + 0.01.
I think that you posted a similar question before with similar code. I understand that you use the timer so that you can update your plots (over time) but why do you have to start from the "beginning" every time the callback fires? Why not use the P1 that you calculated the last timer the callback fired (i.e. the last element of get(handles.P1_signal, 'YData')) and why not start at the time t from the last time the callback fired (i.e. handles.t)?
Try changing your code as follows (I'm assuming that you have already incremented handles.t and that P1 has been initialized to zero) % we use the P1 that was saved the last time the callback fired data = get(handles.P1_signal, 'YData') ; if ~isempty(data) P1 = data(end); end
dt = 0.0001; % no change
for t=(handles.t-0.01):dt:handles.t
% etc.
end
With the above, I observe gradual changes to P1 as Pin is reduced via the slider. I also noticed that the else condition did get executed because P1 no longer snaps to Pin when the slider is invoked.
Try the above and see what happens!
  3 Comments
Gary Chen
Gary Chen on 16 Apr 2016
Geoff - this method worked brilliantly! Thanks for the help!

Sign in to comment.

More Answers (0)

Categories

Find more on Graphics Objects in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!