Trouble passing data between GUI callbacks
2 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Zachary Adamson
el 17 de Jul. de 2017
Comentada: Zachary Adamson
el 17 de Jul. de 2017
Hello!
I am working on a small utility to control and record two Watlow PID controllers via MODBUS. I am currently using MATLAB 2016b which I know does not have MODBUS support, but I am simply using this machine to do most the coding and will move over to a machine with 2017a to finalize the utility.
Here is my problem: I cannot pass data in/out of the handles structure within the recTimerCallback function. Every time the callback runs the handles structure has the same data it initially had, that is handles.Data = [] and handles.Index = 1. I'm not sure what I'm doing wrong and any help would be appreciated!
Here is my code:
function varargout = utilv3(varargin)
% UTILV3 MATLAB code for utilv3.fig
% UTILV3, by itself, creates a new UTILV3 or raises the existing
% singleton*.
%
% H = UTILV3 returns the handle to a new UTILV3 or the handle to
% the existing singleton*.
%
% UTILV3('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in UTILV3.M with the given input arguments.
%
% UTILV3('Property','Value',...) creates a new UTILV3 or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before utilv3_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to utilv3_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help utilv3
% Last Modified by GUIDE v2.5 13-Jul-2017 14:34:03
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @utilv3_OpeningFcn, ...
'gui_OutputFcn', @utilv3_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before utilv3 is made visible.
function utilv3_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to utilv3 (see VARARGIN)
%Varaibles for connecting/reading/writing the controllers
handles.T_Register = 2160; %Thermal register to read
handles.T_IP = '192.168.1.103'; %Thermal PM IP
handles.F_Register = 2160; %Flow register to read
handles.F_IP = '192.168.1.100'; %Flow PM IP
handles.InputReg = 360; %Register to read from
%MODBUS Objects to communicate with the controllers
handles.ThermalBus = modbus('tcpip', handles.T_IP); %Thermal Modbus onject
handles.FlowBus = modbus('tcpip', handles.F_IP); %Flow Modbus object
%Variables for data aqquisition
handles.Data = []; %Where the data will be stored
handles.Index = 1; %Index for recording data
handles.Interval = 0.2; %Interval in seconds between each datapoint
%Timer for continuously monitoring the process values
handles.MonTimer = timer( 'Name', 'ReadTime', ...
'Period', 1.0, ...
'StartDelay', 1, ...
'TasksToExecute', inf, ...
'ExecutionMode', 'fixedspacing', ...
'TimerFcn', {@monTimerCallback, handles});
start(hanldes.MonTimer);
%Timer for continuously recording the process values
handles.recTimer = timer( 'Name', 'RecTime', ...
'Period', 0.2, ...
'TasksToExecute', inf, ...
'ExecutionMode', 'fixedRate', ...
'TimerFcn', {@recTimerCallback, handles});
% Choose default command line output for utilv3
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes utilv3 wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = utilv3_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in ThermalSetpointBtn.
function ThermalSetpointBtn_Callback(hObject, eventdata, handles)
% hObject handle to ThermalSetpointBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%When the button is pressed, write the desired value to the Thermal
%Controller
Mwrite(handles.T_Register, str2double(get(handles.ThermalSetpointBox,'string')), handles.ThermalBus);
% --- Executes on button press in FlowSetpointBtn.
function FlowSetpointBtn_Callback(hObject, eventdata, handles)
% hObject handle to FlowSetpointBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%When the button is pressed, write the desired value to the Flow Controller
Mwrite(handles.F_Register, str2double(get(handles.FlowSetpointBox,'string')), handles.FlowBus);
function ThermalSetpointBox_Callback(hObject, eventdata, handles)
% hObject handle to ThermalSetpointBox (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of ThermalSetpointBox as text
% str2double(get(hObject,'String')) returns contents of ThermalSetpointBox as a double
% --- Executes during object creation, after setting all properties.
function ThermalSetpointBox_CreateFcn(hObject, eventdata, handles)
% hObject handle to ThermalSetpointBox (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
function FlowSetpointBox_Callback(hObject, eventdata, handles)
% hObject handle to FlowSetpointBox (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of FlowSetpointBox as text
% str2double(get(hObject,'String')) returns contents of FlowSetpointBox as a double
% --- Executes during object creation, after setting all properties.
function FlowSetpointBox_CreateFcn(hObject, eventdata, handles)
% hObject handle to FlowSetpointBox (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% --- Executes on button press in ReadingToggleBtn.
function ReadingToggleBtn_Callback(hObject, eventdata, handles)
% hObject handle to ReadingToggleBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hint: get(hObject,'Value') returns toggle state of ReadingToggleBtn
%Timer callback for continuously monitoring the process values and updating
%GUI text strings to match
function monTimerCallback(hObject, eventdata, handles)
%Always update the Set Point text strings
%Read the register for the thermal setpoint and update the string
set(handles.ThermalSetpointTxt, 'string', Mread(handles.F_Register, handles.ThermalBus));
%Read the register for the flow setpoint and update the string
set(handles.FlowSetpointTxt, 'string', Mread(handles.T_Register, handles.FlowBus));
%If monitoring is toggeled, update the Process Value text strings
if get(handles.ReadingToggleBtn,'value') == 1
%Read the register for the thermal process value and update the string
set(handles.ThermalReadingTxt, 'string', Mread(handles.InputReg, handles.ThermalBus));
%Read the register for the flow process value and update the string
set(handles.FlowReadingTxt, 'string', Mread(handles.InputReg, handles.FlowBus));
end
% --- Executes during object deletion, before destroying properties.
function figure1_DeleteFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%Stop the monitoring timer when the GUI is closed
stop(hanldes.MonTimer);
% --- Executes on button press in StartRecBtn.
function StartRecBtn_Callback(hObject, eventdata, handles)
% hObject handle to StartRecBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%Start handles.recTimer to begin recording data
start(handles.recTimer);
%Disable this button
set(handles.StartRecBtn, 'Enable', 'off');
%Enable the stop recording button
set(handles.StopRecBtn, 'Enable', 'on');
% --- Executes on button press in StopRecBtn.
function StopRecBtn_Callback(hObject, eventdata, handles)
% hObject handle to StopRecBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%Stop handles.recTimer to stop recording data
stop(handles.recTimer);
%Disable this button
set(handles.StopRecBtn, 'Enable', 'off');
%Enable the save data button
set(handles.SaveDataBtn, 'Enable', 'on');
%Timer callback for recording the process values when the user desires
function recTimerCallback(hObject, eventdata, handles)
%Write the time value to the first column
handles.Data(handles.Index, 1) = handles.Index * handles.Interval;
%Record the thermal process value
%Write the process value to the second column
handles.Data(handles.Index, 2) = Mread(handles.InputReg, ThermalBus);
%Record the flow process value
%Write the process value to the third column
handles.Data(handles.Index, 3) = Mread(handles.InputReg, FlowBus);
%Increment the index
handles.Index = handles.Index + 1;
guidata(hObject, handles);
% --- Executes on button press in SaveDataBtn.
function SaveDataBtn_Callback(hObject, eventdata, handles)
% hObject handle to SaveDataBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%Write the recorded data to an excel file
xlswrite('TE DATA', handles.Data);
%Empty handles.Data and reset handles.Index so more data can be recorded if
%necessary
handles.Data = [];
handles.Index = 1;
%Disable this button
set(handles.SaveDataBtn, 'Enable', 'off');
%Enable the start recording button
set(handles.StartRecBtn, 'Enable', 'on');
0 comentarios
Respuesta aceptada
Adam
el 17 de Jul. de 2017
You have to use
guidata( hObject, handles )
after assigning new data to the handles structure as the one you have in any given callback is just a local copy and goes out of scope when you do not do this.
7 comentarios
Adam
el 17 de Jul. de 2017
Editada: Adam
el 17 de Jul. de 2017
I've never really used a timer callback myself, but I use a lot of listener callbacks which work the same way. Indeed any user defined callback should work the same way, although there are caveats that you have to be aware of when you end up with nested callbacks in a complicated setup (usually from listeners which cause the code to jump to another callback whilst already in one callback).
The key point is that 'handles' is nothing more than a struct. It looks a bit like some magic kind of struct because of the way it gets passed around internally in GUIDE-defined GUIs, but these do things behind the scenes that a normal user-defined callback doesn't have by default.
When you setup a function handle like the one you did, where 'handles' is an argument 'baked into' the function handle it will just be a time-stamped version of handles at the time you define the callback and will never change after that because it is just a struct locked into the function definition.
Passing the GUI handle means that you can always ask it for the latest version of handles at the point your callback is triggered, not when it was defined. You just have to make sure you aren't changing the GUI figure tag midway through the program, but there is no sensible reason to be doing that!
Más respuestas (0)
Ver también
Categorías
Más información sobre Creating, Deleting, and Querying Graphics Objects en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!