classdef Techno_TCS<handle
    properties
        Serial_Obj
        Ref_Temp
        K
        T1
        T2
        P_val
        I_val
        D_val
        fed_temp
        Calibration_Voltage
        t_arr
        overshoot
        steady_state_error
        rise_time
        max_time
        max_temp
        test_data
        
    end
    
    methods
        function obj=Techno_TCS(com_port)
                close_override();
                obj.Serial_Obj=serial_init(com_port);
                obj.P_val=0;
                obj.D_val=0;
                obj.I_val=0;
                obj.Ref_Temp=60;
                obj.Calibration_Voltage=0.5; %default open_loop voltage to the driver
                obj.max_temp=100; 
                obj.max_time=600; %default total time of the experiment
                
        end
        function set_Openloop_Voltage(obj,value)
            obj.Calibration_Voltage=set_variable(value);
        end
        function set_tot_time(obj,value)
            
            if value < 500
                warning('For accurate results, observation time needs to be more than 5 minutes, reverting back total_time to default of 10 minutes');
                warning('Make sure the value of time entered is in seconds');
            else
                obj.max_time=set_variable(value);
            end
             
        end
        function set_ref(obj,value)
            
            temp=set_variable(value);
            obj.Ref_Temp=round_val(temp,1);
        end
        function set_P(obj,val_P)
            obj.P_val=set_variable(val_P);
        end
        function set_I(obj,val_I)
            obj.I_val=set_variable(val_I);
        end
        function set_D(obj,val_D)
            obj.D_val=set_variable(val_D);
        end
        function curr_temp=read_temp(obj)
            curr_temp=read_signal(obj.Serial_Obj);
        end 
        function curr_temp=read_temp_ol(obj)
            curr_temp=read_signal_ol(obj.Serial_Obj);
        end
        function wait(obj)
                fwrite(obj.Serial_Obj,0);
        end
        function write(obj,data)
                write_signal(obj.Serial_Obj,data);   
        end
        function watch(obj)
                figure(6);
                axis([0 obj.max_time 0 (obj.Ref_Temp+20)]);
                ButtonHandle=uicontrol('Style','PushButton','String','Stop','Callback','delete(gcbf)');
                hold on;
                t=tic;
                while(1)
                fed=obj.read_temp();
                figure(6);
                axis([0 obj.max_time 0 (obj.Ref_Temp+20)])
                plot(toc(t),fed,'.');
                hold on;
                if ~ishandle(ButtonHandle)
                    disp('Loop Stopped');
                    break;
                end
                end
                
            
        end
        function calc_PID(obj)
                [obj.P_val, obj.I_val,obj.D_val]=auto_tune_PID(obj.T1,obj.T2,obj.K);
                 disp('The value of Kp: ');
                 disp(obj.P_val);
                 disp('The value of Ki: ');
                 disp(obj.I_val);
                 disp('The value of Kd: ');
                 disp(obj.D_val);
        end
        function calc_PI(obj)
                [obj.P_val, obj.I_val]=auto_tune_PI(obj.T1,obj.T2,obj.K);
                obj.D_val=0;
                disp('The value of Kp: ');
                disp(obj.P_val);
                disp('The value of Ki: ');
                disp(obj.I_val);
        end
        function calc_P(obj)
                obj.P_val=auto_tune_P(obj.T1,obj.T2,obj.K);
                obj.I_val=0;
                obj.D_val=0;
                disp('The value of Kp: ');
                disp(obj.P_val);
        end
        
        
        
        function open_loop(obj,res_type)
            obj.fed_temp=[];
            obj.test_data=[];
            obj.t_arr=[];
            t=tic;
            figure(1);
            str=sprintf('Open Loop Char');
            title(str)
            axis([0 obj.max_time 0 obj.max_temp]);
            xlabel('Time in Seconds');
            ylabel('Temp in Deg Centigrade');
            ButtonHandle=uicontrol('Style','PushButton','String','Stop','Callback','delete(gcbf)');
            hold on;
            room_temp=obj.read_temp_ol();
            fed=room_temp;
            initial_temp=fed;
            check=1;
            obj.fed_temp(check)=room_temp;
            tend=toc(t);
            obj.t_arr(check)=tend;
            figure(1);
            axis([0 obj.max_time (room_temp-10) obj.max_temp]);
            plot(tend,fed,'.');
            hold on;
            while(1)
                check=check+1;
                sig_send=calc_signal_ol(obj.Calibration_Voltage);
                obj.write(sig_send);
                fed=obj.read_temp_ol();
                figure(1);
                axis([0 obj.max_time (room_temp-10) obj.max_temp]);
                tend=toc(t);
                obj.fed_temp(check)=fed;
                obj.t_arr(check)=tend;
                plot(tend,fed,'.');
                hold on;
                
                if ~ishandle(ButtonHandle)
                    disp('Loop Stopped');
                    break;
                end
               
            end
            obj.wait();
            obj.fed_temp=(smoothing(smoothing((obj.fed_temp))))';
            obj.test_data=[obj.t_arr',obj.fed_temp'];
            len=length(obj.fed_temp);
            final_temp=obj.fed_temp(len);
            obj.K=(obj.fed_temp(len)-initial_temp)/obj.Calibration_Voltage; %formula as mentioned in the manual
            for i = 1:length(obj.fed_temp)
            figure(1);
            axis([0 obj.max_time (room_temp-10) obj.max_temp]);
            plot(obj.t_arr(i),obj.fed_temp(i),'.');
            hold on;
            end
            figure(1);
            title(str);
            axis([0 obj.max_time (room_temp-10) obj.max_temp]);
            hline=refline(0,initial_temp);
             set(hline,'Color','r');
            hold on;
            hline=refline(0,final_temp);
             set(hline,'Color','r');
            hold on;
            xlabel('Time in Seconds');
            ylabel('Temp in Deg Centigrade');
            plot(obj.t_arr,obj.fed_temp);
            txt1=sprintf('K: %.2f',obj.K);
            text((obj.max_time-400),(final_temp+5),txt1);
            hold on;
            [obj.T2,obj.T1]=auto_tune(obj.fed_temp,obj.t_arr,obj.max_time,obj.max_temp,str);
            try
            if isequal(res_type,'P')
                obj.calc_P();
            else if isequal(res_type,'PI')
                obj.calc_PI();
            else if isequal(res_type,'PID')
                 obj.calc_PID();
            else
               disp('Please enter one of the following: 1) P 2) PI 3)PID ');
                end
                end
            end
            catch
                warning('Please enter one of the response types while running the open-loop response');
                warning('Use "calc_P/PI/PID" now to calculate K values for one of the response');
            end
            
                
           txt3=sprintf('Kp %.5f',obj.P_val);
           txt4=sprintf('Ki %.5f',obj.I_val);
           txt5=sprintf('Kd %.5f',obj.D_val);
           figure(1);
           text((obj.max_time-400),(final_temp-5),txt3);
           text((obj.max_time-400),(final_temp-10),txt4);
           text((obj.max_time-400),(final_temp-15),txt5);

           
        end
                
 
            
        function close(obj)
            closing(obj.Serial_Obj);
        end
        function run_PID(obj)
            obj.fed_temp=[];
            obj.test_data=[];
            obj.t_arr=[];
            figure(2);
            axis([0 obj.max_time 0 (obj.Ref_Temp+20)]);
            ButtonHandle=uicontrol('Style','PushButton','String','Stop','Callback','delete(gcbf)');
            hold on;
            t=tic;
            errprev=0; %intialising variables for storing the error of prev. iteration and the integration part
            integral1=0;
            count=1;
            room_temp=obj.read_temp();
            obj.fed_temp(count)=room_temp;%feedback temp
            tend=toc(t);
            dt=tend;
            t_arr(count)=tend;
            figure(2);
            str=sprintf('PID Response with Kp:%.4f Ki:%.4f Kd:%.4f',obj.P_val,obj.I_val,obj.D_val);
            title(str);
            axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
            xlabel('Time in Seconds');
            ylabel('Temp in Deg Centigrade');
            hline = refline([0 obj.Ref_Temp]);
            hline.Color = 'r';
            plot(tend, room_temp,'.');
            hold on;
            

while(1)
    
    t1=tic;
    err=(obj.Ref_Temp-obj.fed_temp(count))/100;
    
    fun_p=calc_P_sig(obj.P_val,err);
    integral1=integral1+(err*dt);
    fun_i=calc_I_sig(obj.I_val*integral1);
    fun_d=calc_D_sig(obj.D_val*(err-errprev)/dt);
    total=fun_p+fun_d+fun_i;
    
    
    if total>0
        sig_send=(total);
    else 
        
        sig_send=0;
    end 

    if(sig_send>=maxi_val())
    	sig_send=max_value();
    end
    obj.write(sig_send);
    fed=obj.read_temp();
    count=count+1; %to check no of iterations   
    obj.fed_temp(count)=fed;
    t2=toc(t1);
    dt=t2;
    errprev=err;
    figure(2)
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    hold on;
    tend=toc(t);
    obj.t_arr(count)=tend;
    plot(tend,fed,'.');
    hold on;
    if ~ishandle(ButtonHandle)
    disp('Loop Stopped');
    break;
    end
    
    
end
obj.wait();
obj.fed_temp=(smoothing(smoothing(smoothing((obj.fed_temp)))))';
obj.test_data=out_data(obj.t_arr,obj.fed_temp);
[obj.overshoot,t_max]=calc_overshoot(obj.fed_temp,obj.test_data);
obj.steady_state_error=calc_steady_state_error(obj.fed_temp,obj.Ref_Temp);
[obj.rise_time,temp_r]=calc_rise_time(obj.fed_temp,obj.test_data);
maxim=max(obj.fed_temp);
disp('The rise time is: ')
disp(obj.rise_time);
disp('The amount of overshoot: ')
disp(obj.overshoot);

disp('The Steady State error is: ')
disp(obj.steady_state_error);
txt0=sprintf('Rise Time: %0.1f sec',round_val(obj.rise_time,1));
txt1=sprintf('Overshoot:%.2f percent',round_val(obj.overshoot,2));
txt2=sprintf('Steady State error: %.2f deg C',round_val(obj.steady_state_error,2));

for i = 1:length(obj.fed_temp)
    figure(2);
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    plot(obj.t_arr(i),obj.fed_temp(i),'.');
    hold on;
end

figure(2);
title(str);
axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
xlabel('Time in Seconds');
ylabel('Temp in Deg Centigrade');
hline = refline([0 obj.Ref_Temp]);
hline.Color = 'r';
plot(obj.t_arr,obj.fed_temp);
plot(obj.rise_time,temp_r,'r*');
plot(t_max, maxim, 'r*');
plot(obj.t_arr(count),obj.fed_temp(count),'r*');
text(obj.max_time/2,((obj.Ref_Temp+20)/2)+5,txt0);
text(obj.max_time/2,((obj.Ref_Temp+20)/2),txt1);
text(obj.max_time/2,((obj.Ref_Temp+20)/2)-5,txt2);
hold on;
        end
        function run_PI(obj)
             obj.fed_temp=[];
            obj.test_data=[];
            obj.t_arr=[];
            figure(3);
            axis([0 obj.max_time 0 (obj.Ref_Temp+20)]);
            ButtonHandle=uicontrol('Style','PushButton','String','Stop','Callback','delete(gcbf)');
            hold on;
            t=tic;
            errprev=0; %intialising variables for storing the error of prev. iteration and the integration part
            integral1=0;
            count=1;
            room_temp=obj.read_temp();
            obj.fed_temp(count)=room_temp;%feedback temp
            tend=toc(t);
            dt=tend;
            t_arr(count)=tend;
            figure(3);
            str=sprintf('PI Response with Kp:%.4f Ki:%.4f',obj.P_val,obj.I_val);
            title(str);
            axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
            xlabel('Time in Seconds');
            ylabel('Temp in Deg Centigrade');
            hline = refline([0 obj.Ref_Temp]);
            hline.Color = 'r';
            plot(tend, room_temp,'.');
            hold on;
            

while(1)
    t1=tic;
    err=(obj.Ref_Temp-obj.fed_temp(count))/100;
    fun_p=calc_P_sig(obj.P_val,err);
    integral1=integral1+(err*dt);
    fun_i=calc_I_sig(obj.I_val*integral1);
    total=fun_p+fun_i;
    if total>0
        sig_send=(total);
    else 
        sig_send=0;
    end
    if(sig_send>=maxi_val())
    	sig_send=max_value();
    end
    obj.write(sig_send);
    fed=obj.read_temp();
    count=count+1; %to check no of iterations   
    obj.fed_temp(count)=fed;
    t2=toc(t1);
    dt=t2;
    errprev=err;
    figure(3);
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    hold on;
    tend=toc(t);
    obj.t_arr(count)=tend;
    plot(tend,fed,'.');
    hold on;
    if ~ishandle(ButtonHandle)
    disp('Loop Stopped');
    break;
    end
    
    
end
obj.wait();
obj.fed_temp=(smoothing(smoothing((obj.fed_temp))))';
obj.test_data=out_data(obj.t_arr,obj.fed_temp);
[obj.overshoot,t_max]=calc_overshoot(obj.fed_temp,obj.test_data);
obj.steady_state_error=calc_steady_state_error(obj.fed_temp,obj.Ref_Temp);
[obj.rise_time,temp_r]=calc_rise_time(obj.fed_temp,obj.test_data);
maxim=max(obj.fed_temp);
disp('The rise time is: ')
disp(obj.rise_time);
disp('Percent overshoot: ')
disp(obj.overshoot);
disp('The Steady State error is: ')
disp(obj.steady_state_error);
txt0=sprintf('Rise Time: %0.1f sec',round_val(obj.rise_time,1));
txt1=sprintf('Overshoot:%.2f percent',round_val(obj.overshoot,2));
txt2=sprintf('Steady State error: %.2f deg C',round_val(obj.steady_state_error,2));

for i = 1:length(obj.fed_temp)
    figure(3);
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    plot(obj.t_arr(i),obj.fed_temp(i),'.');
    hold on;
end

figure(3);
title(str);
axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
xlabel('Time in Seconds');
ylabel('Temp in Deg Centigrade');
hline = refline([0 obj.Ref_Temp]);
hline.Color = 'r';
plot(obj.t_arr,obj.fed_temp);
plot(obj.rise_time,temp_r,'r*');
plot(t_max, maxim, 'r*');
plot(obj.t_arr(count),obj.fed_temp(count),'r*');
text(obj.max_time/2,((obj.Ref_Temp+20)/2)+5,txt0);
text(obj.max_time/2,((obj.Ref_Temp+20)/2),txt1);
text(obj.max_time/2,((obj.Ref_Temp+20)/2)-5,txt2);
hold on;

        end   
        function run_P(obj)
             obj.fed_temp=[];
            obj.test_data=[];
            obj.t_arr=[];
            figure(4);
            axis([0 obj.max_time 0 (obj.Ref_Temp+20)]);
            ButtonHandle=uicontrol('Style','PushButton','String','Stop','Callback','delete(gcbf)');
            hold on;
            t=tic;
            errprev=0; %intialising variables for storing the error of prev. iteration and the integration part
            integral1=0;
            count=1;
            room_temp=obj.read_temp();
            obj.fed_temp(count)=room_temp;%feedback temp
            tend=toc(t);
            dt=tend;
            t_arr(count)=tend;
            figure(4);
            str=sprintf('P Response with Kp:%.4f',obj.P_val);
            title(str);
            axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
            xlabel('Time in Seconds');
            ylabel('Temp in Deg Centigrade');
            hline = refline([0 obj.Ref_Temp]);
            hline.Color = 'r';
            plot(tend, room_temp,'.');
            hold on;
            

while(1)
    t1=tic;
    err=(obj.Ref_Temp-obj.fed_temp(count))/100;
    fun_p=calc_P_sig(obj.P_val,err);
    total=fun_p;
    if total>0
        sig_send=(total);
    else 
        sig_send=0;
    end 

    if(sig_send>=maxi_val())
    	sig_send=max_value();
    end
    obj.write(sig_send)
    fed=obj.read_temp();
    count=count+1; %to check no of iterations   
    obj.fed_temp(count)=fed;
    t2=toc(t1);
    dt=t2;
    errprev=err;
    figure(4);
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    hold on;
    tend=toc(t);
    obj.t_arr(count)=tend;
    plot(tend,fed,'.');
    hold on;
    if ~ishandle(ButtonHandle)
    disp('Loop Stopped');
    break;
    end
    
    
end
obj.wait();
obj.fed_temp=(smoothing(smoothing((obj.fed_temp))))';
obj.test_data=out_data(obj.t_arr,obj.fed_temp);
[obj.overshoot,t_max]=calc_overshoot(obj.fed_temp,obj.test_data);
obj.steady_state_error=calc_steady_state_error(obj.fed_temp,obj.Ref_Temp);
[obj.rise_time,temp_r]=calc_rise_time(obj.fed_temp,obj.test_data);
maxim=max(obj.fed_temp);
disp('The rise time is: ');
disp(obj.rise_time);
disp('Percent overshoot: ');
disp(obj.overshoot);

disp('The Steady State error is: ')
disp(obj.steady_state_error);
txt0=sprintf('Rise Time: %0.1f sec',round_val(obj.rise_time,1));
txt1=sprintf('Overshoot:%.2f percent',round_val(obj.overshoot,2));
txt2=sprintf('Steady State error: %.2f deg C',round_val(obj.steady_state_error,2));

for i = 1:length(obj.fed_temp)
    figure(4);
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    plot(obj.t_arr(i),obj.fed_temp(i),'.');
    hold on;
end

figure(4);
title(str);
axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
xlabel('Time in Seconds');
ylabel('Temp in Deg Centigrade');
hline = refline([0 obj.Ref_Temp]);
hline.Color = 'r';
plot(obj.t_arr,obj.fed_temp);
plot(obj.rise_time,temp_r,'r*');
plot(t_max, maxim, 'r*');
plot(obj.t_arr(count),obj.fed_temp(count),'r*');
text(obj.max_time/2,((obj.Ref_Temp+20)/2)+5,txt0);
text(obj.max_time/2,((obj.Ref_Temp+20)/2),txt1);
text(obj.max_time/2,((obj.Ref_Temp+20)/2)-5,txt2);
hold on;

        end            
        function run_Relay(obj)
             obj.fed_temp=[];
            obj.test_data=[];
            obj.t_arr=[];
            figure(5);
            axis([0 obj.max_time 0 (obj.Ref_Temp+20)]);
            ButtonHandle=uicontrol('Style','PushButton','String','Stop','Callback','delete(gcbf)');
            hold on;
            
            t=tic;
            errprev=0; %intialising variables for storing the error of prev. iteration and the integration part
            integral1=0;
            count=1;
            room_temp=obj.read_temp();
            obj.fed_temp(count)=room_temp;%feedback temp
            tend=toc(t);
            dt=tend;
            t_arr(count)=tend;
            
            figure(5);
            str=('Relay Response');
            title(str);
            axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
            xlabel('Time in Seconds');
            ylabel('Temp in Deg Centigrade');
            hline = refline([0 obj.Ref_Temp]);
            hline.Color = 'r';
            plot(tend, room_temp,'.');
            hold on;
            

while(1)
    t1=tic;
    err=(obj.Ref_Temp-obj.fed_temp(count));

    if err>0
        sig_send=max_value();
    else 
        
        sig_send=0;
    end 
    obj.write(sig_send);
    fed=obj.read_temp();
    count=count+1; %to check no of iterations   
    obj.fed_temp(count)=fed;
    t2=toc(t1);
    dt=t2;
    errprev=err;
    figure(5);
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    hold on;
    tend=toc(t);
    obj.t_arr(count)=tend;
    plot(tend,fed,'.');
    hold on;
    if ~ishandle(ButtonHandle)
    disp('Loop Stopped');
    break;
    end
    
    
end
obj.wait();
obj.fed_temp=(smoothing(smoothing((obj.fed_temp))))';
obj.test_data=out_data(obj.t_arr,obj.fed_temp);
[obj.overshoot,t_max]=calc_overshoot(obj.fed_temp,obj.test_data);
obj.steady_state_error=calc_steady_state_error(obj.fed_temp,obj.Ref_Temp);
[obj.rise_time,temp_r]=calc_rise_time(obj.fed_temp,obj.test_data);
maxim=max(obj.fed_temp);
disp('The rise time is: ');
disp(obj.rise_time);
disp('Percent overshoot: ');
disp(obj.overshoot);

disp('The Steady State error is: ');
disp(obj.steady_state_error);
txt0=sprintf('Rise Time: %0.1f sec',round_val(obj.rise_time,1));
txt1=sprintf('Overshoot:%.2f percent',round_val(obj.overshoot,2));
txt2=sprintf('Steady State error: %.2f deg C',round_val(obj.steady_state_error,2));


for i = 1:length(obj.fed_temp)
    figure(5);
    axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
    plot(obj.t_arr(i),obj.fed_temp(i),'.');
    hold on;
end

figure(5);
title(str);
axis([0 obj.max_time (room_temp-10) (obj.Ref_Temp+20)]);
xlabel('Time in Seconds');
ylabel('Temp in Deg Centigrade');
hline = refline([0 obj.Ref_Temp]);
hline.Color = 'r';
plot(obj.t_arr,obj.fed_temp);
plot(obj.rise_time,temp_r,'r*');
plot(t_max, maxim, 'r*');
plot(obj.t_arr(count),obj.fed_temp(count),'r*');
text(obj.max_time/2,((obj.Ref_Temp+20)/2)+5,txt0);
text(obj.max_time/2,((obj.Ref_Temp+20)/2),txt1);
text(obj.max_time/2,((obj.Ref_Temp+20)/2)-5,txt2);
hold on;

        end   
        function export_data(obj)
A=array2table(obj.test_data,'VariableNames',{'Time_Sec','Temp'});
dname = uigetdir(matlabroot, 'Techno_TCS.xlsx');
filename = 'Techno_TCS.xlsx'
dname = fullfile(dname,filename);
writetable(A,dname);
%writetable(A,dname,'Sheet',1,'Range','D5');
        end
    end
    
end

