Suppose vec_A, vec_B, vec_c are some matrices with random data. I want to write data to text file for every 5 min, My code as follows:
function samplegui_OpeningFcn(hObject, ~, handles, varargin)
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 300, ... % Initial period.
'TimerFcn', {#open,hObject}); % Specify callback
handles.output = hObject;
handles.vec_A=[];
handles.vec_B=[];
handles.vec_C=[];
guidata(hObject, handles);
function open_Callback(hObject, eventdata, handles) % push button to receive serial data.
cnt=0;
while 1
% Getting data from Serial Port
get_lines=fgets(handles.se) % getting data from serial port
if~isempty(get_lines)
cnt=cnt+1;
if strfind(get_lines,'T') %Parsing data
handles.vec_A=[handles.vec_A;[timet newword]];
plot(handles.vec_A(:,1),handles.vec_A(:,2:end),'r'); % plotting
% Same follows for parsing and plot vec_B and Vec_C
drawnow(); % to update the Plots
end
end
Pause(.05);
start(handles.timer); % saving the data
dlmwrite('My_sample1.txt',handles.vec_A);
dlmwrite('My_sample2.txt',handles.vec_B);
dlmwrite('My_sample3.txt',handles.vec_C);
stop(handles.timer);
end
guidata(hObject, handles);
While running my code, following error occurs:
Error while evaluating TimerFcn for timer 'timer-6'
Too many input arguments.
How to execute timer in this case to write data successfully for every five minutes or suggest any other way to do it.
You have defined your TimerFcn to be {#open, hObject} but you don't have a function named open. Instead, it is trying to call the built-in open with three input arguments (the timer object, an event object, and hObject) and this is producing the error because open only accepts one input argument.
That being said, it's not clear at all how the code that you have provided will accomplish anything close to what you want. Something like this may work better.
function samplegui_OpeningFcn(hObject, ~, handles, varargin)
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 300, ... % Initial period.
'TimerFcn', #(s,e)write_data()); % Specify callback
handles.output = hObject;
handles.vec_A=[];
handles.vec_B=[];
handles.vec_C=[];
guidata(hObject, handles);
start(handles.timer);
%// Now update your data in a loop
cnt = 0;
while true
%// Getting data from Serial Port
get_lines = fgets(handles.se)
if ~isempty(LINES)
cnt = cnt + 1;
if strfind(LINES, 'T')
handles.vec_A = [handles.vec_A; [timet newword]];
plot(handles.vec_A(:,1), handles.vec_A(:,2:end),'r');
drawnow
end
end
end
function write_data()
%// Write it to file
dlmwrite('My_sample1.txt',handles.vec_A);
dlmwrite('My_sample2.txt',handles.vec_B);
dlmwrite('My_sample3.txt',handles.vec_C);
end
end
Related
I built a GUI using the GUIDE feature in Matlab. I have many push buttons. I start by clicking one push button to start tic. Then when I click any of the other push buttons, I want to build a vector of toc time stamps. How do I do this?
The most robust solution is to store and manipulate the vector in the GUI's handles structure. First, in your "create function", initialize the start and stop vectors:
function yourGui_CreateFcn ( hObject , eventdata , handles )
% Initialize the start and stop vectors.
handles.timeStart = [];
handles.timeStop = [];
% Update the GUI handles structure.
guidata ( hObject , handles );
end
Then, in your first button, start the timer and store it to your handles vector.
function button1_Callback ( hObject , eventdata , handles )
% Start the timer, updating the value in the handles structure.
handles.timeStart = tic;
% Update the GUI data so that timer is available to other functions.
guidata ( hObject , handles );
end
Next, in each of your other button callbacks, retrieve the starting time from the handles structure and determine the elapsed time:
function button2_Callback ( hObject , eventdata , handles )
% Retrieve the start time.
timeStart = handles.timeStart;
% Determine the elapsed time.
timeElapsed = toc ( timeStart );
% Store the new value in the handles structure.
handles.timeStop(end+1,1) = timeElapsed;
% Update the guidata.
guidata ( hObject , handles );
end
Finally, you can output the values from the GUI using the "output function".
function yourGui_OutputFcn ( hObject , eventdata , handles )
% Specify the output variables.
varargout { 1 } = handles . timeStart;
varargout { 2 } = handles . timeStop;
end
You would then execute your gui using the following statement in the command line:
>> [timeStart,timeStop] = yourGui ( );
I get the following error message about too many input arguments in my fprintf function. But it seems to me that just the right amount of arguments were passed.
All this is in the context of a guide GUI I made (see picture at the end).
Error while evaluating uicontrol Callback
calibration button hit
20
200
10
10
2520
25197
2520
25197
'C0 2520 25197 10 10'
Error using serial/fprintf (line 115)
Too many input arguments.
Error in UserInterface>StaticCalibrationBtn_Callback (line 202)
fprintf(handles.s, 'C0 %s %s %s %s',StartStepsStr,EndStepsStr,Increment,Wait);
Here is the code
function StaticCalibrationBtn_Callback(hObject, eventdata, handles)
% hObject handle to StaticCalibrationBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
disp('calibration button hit');
Start = str2double(get(handles.CalFromUserTxt, 'string')); % Fetches the user inputed start location in mm and converts to double
disp(Start);
End = str2double(get(handles.CalToUserTxt, 'string')); % same for End position
disp(End);
Increment = get(handles.CalUserIncrementTxt, 'string'); % fetches the increment user inputed data as a string
disp(Increment);
Wait = get(handles.CalUserSpeedTxt, 'string'); % fetches the wait inputed data as a string
disp(Wait);
StartSteps = round(Start/0.00793750000); % computes the starting step position,double division
disp(StartSteps);
handles.StartSteps = StartSteps; % creats a place for the start steps inside the handles structure, to be fetched by anythingelsest be saved with guidata(hObject,handles)
EndSteps = round(End/0.00793750000); % computes the end step position
disp(EndSteps);
handles.EndSteps = EndSteps; % stores the end steps to be accessed by anything else must be saved with guidata(hObject,handles)
StartStepsStr = num2str(StartSteps); % converts the StartSteps double into a string so it can be sent over serial as a string
disp(StartStepsStr);
EndStepsStr = num2str(EndSteps); % converts the EndSteps double into a string so it can be sent over serial as a string
disp(EndStepsStr);
OutputString = strcat('C0' , {' '} , StartStepsStr , {' '} , EndStepsStr , {' '} , Increment , {' '} , Wait);
disp(OutputString);
fprintf(handles.s, 'C0 %s %s %s %s',StartStepsStr,EndStepsStr,Increment,Wait);
and where handles.s comes from
function SerialBtn_Callback(hObject, eventdata, handles)
% hObject handle to SerialBtn (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA
comPort = get(handles.COMportTxt,'String');
if(~exist('serialFlag','var'))
[handles.s, handles.serialFlag] = setupSerial(comPort);
end
guidata(hObject,handles);
end
And the setupserial funciton
function [ s, flag] = setupSerial(comPort)
%Initialize serial port communication between Arduino and Matlab
%Ensure that the arduino is also communicating with Matlab at this time.
%if setup is complete then the value of setup is returned as 1 else 0.
flag =1;
s = serial(comPort);
set(s,'DataBits',8);
set(s,'StopBits',1);
set(s,'BaudRate',9600);
set(s,'Parity','none');
fopen(s);
a='b';
while (a~='a')
a=fread(s,1,'uchar');
end
if (a=='a')
disp('serial read');
end
fprintf(s,'%c','a');
mbox = msgbox('Serial Communication setup.'); uiwait(mbox);
fscanf(s,'%u');
end
USING THE FOLLOWING RESOLVED THE ISSUE
OutputString = sprintf('C0 %s %s %s %s',StartStepsStr,EndStepsStr,Increment,Wait);
fprintf(handles.s,'%s', OutputString);
There are multiple functions called fprintf, one for files, one for serial objects and some others. You are using functionally which you know from the fprintf for files, but you are using it with a serial object. Check the right documentation which can be accessed via doc serial/fprintf
I am working with serial port and multiple list boxes to read data in serial port. The listboxes are used to read specific data (suppose the data is coming from 3 different sources, so I have 3 listboxes).
Now the problem:
I want to read all the data separately and continuously. I mean, when I am clicking one listbox (e.g. listbox#2) after reading listbox#1's data, the listbox#1 automatically stops, so again I need to click listbox#1 to read the data for listbox#1. But I want to get the data continuously in all the listboxes without clicking (clicking for first time to initializing) every time. How can I achieve this? I have tried other ways but not working.
Additional comment: It worked as per the below comments.
Sample code [Edited and OpeningFcn has been added]:
function main_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Initial period is 1 sec.
'TimerFcn', {#listbox1_Callback, handles});
guidata(hObject, handles);
function listbox1_Callback(hObject, eventdata, handles)
%serConn is the connection to COM port
out = fscanf(handles.serConn);
string = 'degrees1';
t=1;
while(t < 15)
if strncmp(out,string,8)
rxtext = out(14:15);
currList = get(handles.listbox, 'String');
set(handles.listbox,'String',...
[currList ; [temp]]);
end
pause(5);
t = t+1;
end
Trying to use Timer in GUI. While attempting in following code it is showing error.
function main_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Initial period is 1 sec.
'TimerFcn', {#send_Callback,hObject});
guidata(hObject, handles);
function send_Callback(hObject, eventdata, handles)
comma = get(handles.Tx_send, 'String');%Tx_send is a text field
TxText = char(comma);
sf = rc4e2(TxText,key);%rc4e2 is an encryption
key = TxText;
DBC = char(sf);
disp(DBC);
fwrite(handles.serConn, DBC);%serConn is COM port
The error: Error while evaluating TimerFcn for timer 'timer-1'. Attempt to reference field of non-structure array.
Try changing your timerFcn to {'send_Callback',handles}.
In your version (as written in the original question), you have to write
'TimerFcn', {#send_Callback,handles});
The reason MATLAB is showing this error is because when it calls the Callback function, it automatically passes the timer handle as first argument and an empty event structure as second argument. The argument you provide by using the cell array is the third one. This means, your send_Callback is called with the argument list handles.timer,event,hObject (in this case, hObject is the window handle).
Then in the Callback function, you try to access handles.Tx_send, but since handles is the third argument and you provided just the window handle as the third argument, MATLAB will try to access handles.output.Tx_send, which does not exist.
Passing handles as described above should solve your problem because then the callback will have access to the handles object.
I have a problem in my GUI. In my opening function I defined an img_new variable to be an image I have stored.
My GUI has two axes, one displays the original image and the other one the filtered one. I have 4 filters in a panel with the 4 radiobuttons. And in the end of each one's code there's the img_new = the image created through the radiobutton filter.
Here's some code:
% --- Executes when selected object is changed in uipanel3.
function uipanel3_SelectionChangeFcn(hObject, eventdata, handles)
handles.count = handles.count + 1;
% Change filter orientation depending on which radiobutton is chosen
switch get(eventdata.NewValue,'Tag')
case 'hte'
h_te = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(h_te);
handles.img_new = h_te;
case 'hc'
h_c = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(h_c);
handles.img_new = h_c;
case 'vlr'
v_lr = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(v_lr);
handles.img_new = v_lr;
case 'vc'
v_c = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(v_c);
handles.img_new = v_c;
end
guidata(hObject, handles)
and here's the imwrite function:
% --------------------------------------------------------------------
function save_img_ClickedCallback(hObject, ~, handles)
% writing the new image
imwrite(handles.img_new, strcat('filtered_image_', num2str(handles.count), '.png'));
guidata(hObject, handles)
Here's the function to get the image to axes1 the original) and filter it to axes2 (filtered)
% --- Executes on button press in img2.
function img2_Callback(hObject, ~, handles)
% Read image 2
img = imread('./coimbra_estadio.jpg');
handles.img_d = im2double(img);
% image size
size_img = size(handles.img_d);
handles.colums = size_img(2);
handles.rows = size_img(1);
if rem(handles.rows,2) == 0
handles.row_0 = ((handles.rows/2)+1);
else
handles.row_0 = ((handles.rows/2)+0.5);
end
if rem(handles.colums,2) == 0
handles.colum_0 = ((handles.colums/2)+1);
else
handles.colum_0 = ((handles.colums/2)+0.5);
end
axes(handles.axes1);
imshow(img);
% Generate eventdata to call the radiobuttons function
eventdata_new.EventName = 'SelectionChanged';
eventdata_new.OldValue = get(handles.uipanel3,'SelectedObject');
eventdata_new.NewValue = get(handles.uipanel3,'SelectedObject');
uipanel3_SelectionChangeFcn(handles.uipanel3, eventdata_new, handles);
guidata(hObject, handles)
As you can see, in the end I call the panel function so when the image is loaded it is automatically filtered and the axes2 image changes.
The problem is when I call the save function it saves the old img_new.
If I change the radiobutton the img_new is refreshed, but if it is not changed it is not refreshed. It should be as loading an image automatically calls for the panel of radiobuttons function.
The problem is that guidata(hObject,handles); at the end of img2_Callback saves old handles object as a final gui state, updates made in uipanel3_SelectionChangeFcn are lost. You need to eitehr manually update handles after calling uipannel3_SelectionChangeFcn by putting handles = guidata(hObject,handles);
or handles=guidata(hObject);
(forgot which call to guidata updates handles, please see help for that), or simply remove the line guidata(hObject,handles); at the end of img2_callback (less safe if code is going to change later, updating handles after uipannel3_SelectionChangeFcn is safer approach...