%This application is intended for use with designed flow meter. It reads data
%from specified COM port, performs flow signal voltage filtration 
%with filter specified by user and computes corresponding flow and temperature
%values by using interpolation from look-up tables specified in this code. 
%Battery voltage is computed by simple multiplication. All these values are
%then displayed in plots  in the right half of graphical interface. Measured 
%data can be also saved to the hard drive in .csv format. The whole created
%code is written in functions GUI_receiver_OpeningFcn(),
%Receive_toggle_button_Callback(), ReDraw_Callback() and
%Save_button_Callback(). The rest of this code is automatically generated
%by Matlab guide.

%Auhor: Jindrich Sindelar


function varargout = GUI_receiver(varargin)
%GUI_RECEIVER M-file for GUI_receiver.fig
%      GUI_RECEIVER, by itself, creates a new GUI_RECEIVER or raises the existing
%      singleton*.
%
%      H = GUI_RECEIVER returns the handle to a new GUI_RECEIVER or the handle to
%      the existing singleton*.
%
%      GUI_RECEIVER('Property','Value',...) creates a new GUI_RECEIVER using the
%      given property value pairs. Unrecognized properties are passed via
%      varargin to GUI_receiver_OpeningFcn.  This calling syntax produces a
%      warning when there is an existing singleton*.
%
%      GUI_RECEIVER('CALLBACK') and GUI_RECEIVER('CALLBACK',hObject,...) call the
%      local function named CALLBACK in GUI_RECEIVER.M with the given input
%      arguments.
%
%      *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 GUI_receiver

% Last Modified by GUIDE v2.5 04-May-2015 15:17:15

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @GUI_receiver_OpeningFcn, ...
                   'gui_OutputFcn',  @GUI_receiver_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 GUI_receiver is made visible.
function GUI_receiver_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   unrecognized PropertyName/PropertyValue pairs from the
%            command line (see VARARGIN)

% Choose default command line output for GUI_receiver
handles.output = hObject;

clc

axes(handles.FLOW_voltages);
xlabel('time [s]');
ylabel('Flow voltage [V]');

axes(handles.TEMP_voltages);
xlabel('time [s]');
ylabel('NTC voltage [V]');

axes(handles.VCC_voltages);
xlabel('time [s]');
ylabel('Reference divider voltage [V]');

axes(handles.flow_values);
xlabel('time [s]');
ylabel('Q_V [m^3/h]');

axes(handles.temp_values);
xlabel('time [s]');
ylabel('T [°C]');

axes(handles.Vcc_values);
xlabel('time [s]');
ylabel('Battery voltage [V]');

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes GUI_receiver wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = GUI_receiver_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;



function PORT_NAME_Callback(hObject, eventdata, handles)
% hObject    handle to PORT_NAME (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 PORT_NAME as text
%        str2double(get(hObject,'String')) returns contents of PORT_NAME as a double


% --- Executes during object creation, after setting all properties.
function PORT_NAME_CreateFcn(hObject, eventdata, handles)
% hObject    handle to PORT_NAME (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 BUFFER_SIZE_textbox_Callback(hObject, eventdata, handles)
% hObject    handle to BUFFER_SIZE_textbox (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 BUFFER_SIZE_textbox as text
%        str2double(get(hObject,'String')) returns contents of BUFFER_SIZE_textbox as a double


% --- Executes during object creation, after setting all properties.
function BUFFER_SIZE_textbox_CreateFcn(hObject, eventdata, handles)
% hObject    handle to BUFFER_SIZE_textbox (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 Receive_toggle_button.
function Receive_toggle_button_Callback(hObject, eventdata, handles)
% hObject    handle to Receive_toggle_button (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 Receive_toggle_button

    PORTx = get(handles.PORT_NAME, 'String');
    
    BUFFER_L = str2num(get(handles.BUFFER_SIZE_textbox, 'String'));
     
    Ucc_ = zeros(BUFFER_L, 1);          %create empty arrays for input values - to ensure application speed
    temp_ = zeros(BUFFER_L, 1);
    flow_ = zeros(BUFFER_L, 1);
    
% Create the serial port object if it does not exist
% otherwise use the object that was found.
    s = instrfind('Type', 'serial', 'Port', PORTx, 'Tag', '');
    if isempty(s)
        s = serial(PORTx);
    else
        fclose(s);
        s = s(1);
    end
    
    N_of_chars = 22;
    timeout = 0.055;
    set(s, 'BaudRate', 9600, 'Parity',  'none', 'DataBits', 8, 'StopBits', 1, 'InputBufferSize', N_of_chars, 'Terminator', 'LF', 'TimeOut', timeout);

    fopen(s);
    
    i = 1;
    Qstep = 3.66E-4;            %quantisation step
    Rd1 = 470E3;
    Rd2 = 470E3;                %resistors in voltage divider for supply voltage measurement

    while(get(hObject, 'Value'))
        Buff = fscanf(s);
        if (length(Buff) > 0)
            Ucc_(i) = Qstep*str2num(Buff((strfind(Buff, 'V=')+2):(strfind(Buff, 'V=')+6)));
            temp_(i) = Qstep*str2num(Buff((strfind(Buff, 'T=')+2):(strfind(Buff, 'T=')+6)));
            flow_(i) = Qstep*str2num(Buff((strfind(Buff, 'F=')+2):(strfind(Buff, 'F=')+6)));
            i = i+1;
        end
        pause(0.001);
    end
    
    s = serial(PORTx);
    fclose(s);
    delete(s);

    Ucc_ = Ucc_(1:i);
    temp_ = temp_(1:i);
    flow_ = flow_(1:i);
    
    Ucc_out = Ucc_*(Rd1+Rd2)/Rd2;
    temp_ratio = temp_./Ucc_out;
    
    temp_ratio_table = [0.00493660898914396,0.0126116609593834,0.0202867129296227,0.0279617648998621,0.0356368168701015,0.0433118688403409,0.0509869208105803,0.0586619727808197,0.0663370247510591,0.0740120767212985,0.0816871286915379,0.0893621806617773,0.0970372326320167,0.104712284602256,0.112387336572495,0.120062388542735,0.127737440512974,0.135412492483214,0.143087544453453,0.150762596423692,0.158437648393932,0.166112700364171,0.173787752334411,0.181462804304650,0.189137856274889,0.196812908245129,0.204487960215368,0.212163012185608,0.219838064155847,0.227513116126086,0.235188168096326,0.242863220066565,0.250538272036805,0.258213324007044,0.265888375977283,0.273563427947523,0.281238479917762,0.288913531888002,0.296588583858241,0.304263635828480,0.311938687798720,0.319613739768959,0.327288791739199,0.334963843709438,0.342638895679677,0.350313947649917,0.357988999620156,0.365664051590396,0.373339103560635,0.381014155530874,0.388689207501114,0.396364259471353,0.404039311441593,0.411714363411832,0.419389415382071,0.427064467352311,0.434739519322550,0.442414571292789,0.450089623263029,0.457764675233268,0.465439727203508,0.473114779173747,0.480789831143986,0.488464883114226];
    temp_table = [155,117.221839965260,100.041223505264,89.1781574973408,81.2701753563560,74.9800170270986,69.8813643857277,65.6030813407000,61.9259718680693,58.6217601723822,55.6371844078339,53.0359455377087,50.5387610219524,48.3586330368021,46.2657270958045,44.3038012359741,42.5422976170018,40.7807939980295,39.1742981223834,37.6912119829658,36.2081258435482,34.7665390114272,33.5072926349561,32.2480462584850,30.9887998820138,29.7685192596820,28.6907042780046,27.6128892963272,26.5350743146498,25.4572593329724,24.4611673388773,23.5252933105171,22.5894192821570,21.6535452537968,20.7176712254367,19.8080349445828,18.9846948806120,18.1613548166411,17.3380147526702,16.5146746886993,15.6913346247285,14.8822467504706,14.1477999840590,13.4133532176474,12.6789064512359,11.9444596848243,11.2100129184128,10.4755661520012,9.76291755275682,9.09031239401488,8.41770723527295,7.74510207653101,7.07249691778907,6.39989175904714,5.72728660030520,5.05468144156327,4.41991628387960,3.78849967189680,3.15708305991400,2.52566644793120,1.89424983594840,1.26283322396560,0.631416611982798,0];
    
    for j = 1:i
        temp_out(j) = interp1(temp_ratio_table, temp_table, temp_ratio(j));     %look-up table realization
    end
    
    
    
    pause(0.05);
    
	xaxis = 0:0.05:(i-1)*0.05;                                              %generate x-axis - step is given by ADC sampling rate
   
    %plot input voltages
    plot(handles.FLOW_voltages, xaxis, flow_);
    plot(handles.TEMP_voltages, xaxis, temp_);
    plot(handles.VCC_voltages, xaxis, Ucc_);
    
    %plot output temperature and supply voltage
    plot(handles.temp_values, xaxis, temp_out);
    axes(handles.temp_values);
    ylim([0 60]);
    plot(handles.Vcc_values, xaxis, Ucc_out);
    
    %load local variables into global handles structure
    handles = guidata(hObject);                                             
    handles.flow_ = flow_;
    handles.xaxis = xaxis;
    handles.temp_out = temp_out(1:end-1);
    handles.Ucc_out = transpose(Ucc_out(1:end-1));
    guidata(hObject, handles);
    
    axes(handles.FLOW_voltages);
    xlabel('time [s]');
    ylabel('Flow voltage [V]');

    axes(handles.TEMP_voltages);
    xlabel('time [s]');
    ylabel('NTC voltage [V]');

    axes(handles.VCC_voltages);
    xlabel('time [s]');
    ylabel('Reference divider voltage [V]');

    axes(handles.temp_values);
    xlabel('time [s]');
    ylabel('T [°C]');

    axes(handles.Vcc_values);
    xlabel('time [s]');
    ylabel('Battery voltage [V]');


function WINDOW_length_Callback(hObject, eventdata, handles)
% hObject    handle to WINDOW_length (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 WINDOW_length as text
%        str2double(get(hObject,'String')) returns contents of WINDOW_length as a double


% --- Executes during object creation, after setting all properties.
function WINDOW_length_CreateFcn(hObject, eventdata, handles)
% hObject    handle to WINDOW_length (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 ReDraw.
function ReDraw_Callback(hObject, eventdata, handles)
% hObject    handle to ReDraw (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
Filter_types = get(handles.FilterType, 'String');
Filter_t = Filter_types{get(handles.FilterType, 'Value')};
Window_L = str2num(get(handles.WINDOW_length, 'String'));

handles = guidata(hObject);
flow_ = handles.flow_;
xaxis = handles.xaxis;

    switch (Filter_t)
        case 'rectangular FIR'
            filtered_flow = filtfilt(ones(Window_L, 1)/Window_L, 1, flow_);
        case 'Hann FIR'
            filtered_flow = filtfilt(window(@hann, Window_L)/sum(window(@hann, Window_L)), 1, flow_);
        case 'median filter'
            filtered_flow = medfilt1(flow_, Window_L);
    end

% flow lookup table
flow_voltage_table = [0.000732000000000000,0.00998296551724138,0.0192339310344828,0.0284848965517241,0.0377358620689655,0.0469868275862069,0.0562377931034483,0.0654887586206897,0.0747397241379310,0.0839906896551724,0.0932416551724138,0.102492620689655,0.111743586206897,0.120994551724138,0.130245517241379,0.139496482758621,0.148747448275862,0.157998413793103,0.167249379310345,0.176500344827586,0.185751310344828,0.195002275862069,0.204253241379310,0.213504206896552,0.222755172413793,0.232006137931034,0.241257103448276,0.250508068965517,0.259759034482759,0.269010000000000,0.278260965517241,0.287511931034483,0.296762896551724,0.306013862068966,0.315264827586207,0.324515793103448,0.333766758620690,0.343017724137931,0.352268689655172,0.361519655172414,0.370770620689655,0.380021586206897,0.389272551724138,0.398523517241379,0.407774482758621,0.417025448275862,0.426276413793103,0.435527379310345,0.444778344827586,0.454029310344828,0.463280275862069,0.472531241379310,0.481782206896552,0.491033172413793,0.500284137931034,0.509535103448276,0.518786068965517,0.528037034482759,0.537288000000000];
flow_values_table = [0.100000000000000,0.283072100313480,0.373599137931035,0.444283121597096,0.502298850574713,0.554575596816976,0.602853745541023,0.646432818073722,0.686260775862069,0.724973876698015,0.762512315270936,0.798620689655173,0.832851817334576,0.866136162687887,0.898541114058356,0.930172413793103,0.961767241379310,0.993362068965517,1.02376847290640,1.05376904570970,1.08315958299920,1.11255012028869,1.14194065757819,1.17133119486768,1.20072173215718,1.23011226944667,1.25928683385580,1.28800940438871,1.31752873563218,1.34761904761905,1.37706495589415,1.40677039529016,1.43759461732548,1.46841883936081,1.49924306139613,1.53081896551724,1.56273209549072,1.59513704686118,1.62826678765880,1.66216475095785,1.69727011494253,1.73330049261084,1.77058516196447,1.80915948275862,1.84865301724138,1.88937708565072,1.93222354340071,1.97771392081737,2.02546419098143,2.07607758620690,2.12998500749625,2.18825944170772,2.25095785440613,2.32241379310345,2.39967672413793,2.48912466843501,2.59749216300941,2.73577586206897,3];

%lookup table correction
flow_values_table = flow_values_table/0.85;

for i = 1:length(flow_)
    if (filtered_flow(i) < max(flow_voltage_table))
        flow_out(i) = interp1(flow_voltage_table, flow_values_table, filtered_flow(i));
    else
        flow_out(i) = 3;
    end
end

%plotyy(handles.FLOW_voltages, xaxis, filtered_flow(1:i), xaxis, temp_(1:i));
axes(handles.flow_values);
plot(xaxis, flow_out);
ylim([0 3]);
grid on;

axes(handles.flow_values);
xlabel('time [s]');
ylabel('Q_V [m^3/h]');

% write local output flow values to global handle structure
handles = guidata(hObject);                                             
handles.flow_out = flow_out(1:end-1);
guidata(hObject, handles);
    

            

% Hint: get(hObject,'Value') returns toggle state of ReDraw


% --- Executes on selection change in FilterType.
function FilterType_Callback(hObject, eventdata, handles)
% hObject    handle to FilterType (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns FilterType contents as cell array
%        contents{get(hObject,'Value')} returns selected item from FilterType


% --- Executes during object creation, after setting all properties.
function FilterType_CreateFcn(hObject, eventdata, handles)
% hObject    handle to FilterType (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu 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 Save_button.
function Save_button_Callback(hObject, eventdata, handles)
% hObject    handle to Save_button (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
header = {'time','temp','volt','flow'};

handles = guidata(hObject); 
xaxis = handles.xaxis(1:end-1);
temp_out = handles.temp_out;
volt_out = handles.Ucc_out;
flow_out = handles.flow_out;
guidata(hObject, handles);

[filename, path] = uiputfile('*.csv', 'Save measured output values as');
data_array = transpose([xaxis; temp_out; volt_out; flow_out]);

csvwrite_with_headers([sprintf('%s', path) '\' sprintf('%s', filename)], data_array, header);



