unit mainunit; //{$mode objfpc}{$H+} {$mode delphi} {$H+} //{$define evalue} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, CustomDrawnControls,Dos, Spin, StdCtrls, CustomDrawn_Common, ExtCtrls, TAGraph, TASeries, TATools, TAChartUtils, Types, Process, TADrawUtils, LCLType, TAChartAxisUtils, TACustomSource, TATypes, TAFuncSeries; type { Tmain } Tmain = class(TForm) ChartConstantLine1: TConstantLine; ChartConstantLine2: TConstantLine; BaseFuncSeries: TFuncSeries; Command: TEdit; FitbaseButton: TCDButton; LinFuncSeries: TFuncSeries; ExpFuncSeries: TFuncSeries; IntButton: TCDButton; FitlinButton: TCDButton; FitexpButton: TCDButton; RButton: TCDButton; OpenDialog: TOpenDialog; mtimeedit: TEdit; RedrawButton: TCDButton; SelectDirectoryDialog: TSelectDirectoryDialog; T0Edit: TEdit; REdit: TFloatSpinEdit; TimeEditbox: TEdit; TempChartLineSeries: TLineSeries; TempChart: TChart; ChartToolset: TChartToolset; ChartToolsetDataPointDragTool: TDataPointDragTool; TempmaxEdit: TFloatSpinEdit; poweredit: TEdit; TempminEdit: TFloatSpinEdit; StartButton: TCDButton; SaveButton: TCDButton; TimeEdit: TFloatSpinEdit; Timer1: TTimer; UEdit: TFloatSpinEdit; TempheaterButton: TCDButton; TempheaterEdit: TFloatSpinEdit; Tempheater: TEdit; Uout: TEdit; QuitButton: TCDButton; SaveDialog: TSaveDialog; SaveimageButton: TCDButton; Timer: TTimer; T: TEdit; UoutButton: TCDButton; ManualButton: TCDButton; procedure BaseFuncSeriesCalculate(const AX: Double; out AY: Double); procedure ChartToolsetDataPointDragToolAfterMouseUp(ATool: TChartTool; APoint: TPoint); procedure ChartToolsetDataPointDragToolDrag(ASender: TDataPointDragTool; var AGraphPoint: TDoublePoint); procedure CommandKeyPress(Sender: TObject; var Key: char); procedure ExpFuncSeriesCalculate(const AX: Double; out AY: Double); procedure FitbaseButtonClick(Sender: TObject); procedure FitexpButtonClick(Sender: TObject); procedure FitlinButtonClick(Sender: TObject); procedure IntButtonClick(Sender: TObject); procedure LinFuncSeriesCalculate(const AX: Double; out AY: Double); procedure REditKeyPress(Sender: TObject; var Key: char); procedure REditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure RedrawButtonClick(Sender: TObject); procedure TempChartAfterDraw(ASender: TChart; ADrawer: IChartDrawer); procedure TempheaterButtonClick(Sender: TObject); procedure TempminEditChange(Sender: TObject); procedure TimeEditKeyPress(Sender: TObject; var Key: char); procedure TimeEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Timer1Timer(Sender: TObject); procedure UEditChange(Sender: TObject); procedure TempheaterEditKeyPress(Sender: TObject; var Key: char); procedure TempheaterEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TempmaxEditKeyPress(Sender: TObject; var Key: char); procedure TempmaxEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure StartButtonClick(Sender: TObject); procedure TempminEditKeyPress(Sender: TObject; var Key: char); procedure TempminEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure SaveButtonClick(Sender: TObject); procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); procedure UEditKeyPress(Sender: TObject; var Key: char); procedure UEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ManualButtonClick(Sender: TObject); procedure QuitButtonClick(Sender: TObject); procedure SaveimageButtonClick(Sender: TObject); procedure TimerTimer(Sender: TObject); procedure UoutButtonClick(Sender: TObject); private public end; var main: Tmain; mainpath:string; paramsavefile:string='version'; R:double=4.60; version:longint=1; procedure paramout; implementation uses comUSB, math,utypes,umulfit,unlfit,ufft,uregtest,connect; {$R *.lfm} type data_t=record uout_set:double; uout:double; T_target:double; Tc:double; T:double; T_out:double; power:double; mtime:double; end; { Tmain } const DATASIZE=20000; var savefile:String; {$ifdef LINUX} imagedirectory:string='meaaures/'; savedirectory:string='measures/'; bbs:string='/'; {$else} imagedirectory:string='prints\'; savedirectory:string='measures\'; bbs:string='\'; {$endif} curdata:data_t; manualb:boolean=true; timepointer:longint=0; hours: word; minutes: word; seconds: word; milliseconds: word; connected:boolean=false; running:boolean=false; uoutrunning:boolean=false; datanum:longint=0; data_list:array[0..DATASIZE] of data_t; saverequest:boolean=false; imagenum:longint=0; a0,a,T0,T_zero:double; da0,da,dT0,dT_zero:double; int:double; T_out,beta,T_0,deltaT:double; dT_out,dbeta,dT_0,ddeltaT:double; XX : TMatrix; YY : TVector; Ycalc : TVector; XXn : TVector; B : TVector; V : TMatrix; n0,n1:longint; basefitb:boolean=false; linfitb:boolean=false; expfitb:boolean=false; intb:boolean=false; basedone:boolean=false; linedone:boolean=false; expdone:boolean=false; timemax:double; mtime:double; mtime_0:double; C_p:double=1; dC_p:double; alpha:double=1; dalpha:double; C_p_base:double=1; alpha_base:double=1; dalpha_base:double; U_h:double; t1,t2:double; T_cham,T_inft,T_t,Q:double; notconnected:boolean=false; texp1,texp2,tint1,tint2:double; {$ifdef evalue} evalueb:boolean=true; {$else} evalueb:boolean=false; {$endif} function get_instdir:string; var ss:string; begin ss:=paramstr(0); {$IFDEF LINUX} get_instdir:=copy(ss,1,pos('calori_labor',ss)-1)+'calori_labor/'; mainpath:=getuserdir; //+'calori_labor/'; {$ELSE} get_instdir:=copy(ss,1,pos('calori_labor.exe',ss)-1); mainpath:=get_instdir; {$ENDIF} end; procedure initvalues; var res:longint; s:string; begin s:=get_instdir; imagedirectory:=mainpath+imagedirectory; savedirectory:=mainpath+savedirectory; if evalueb then begin if res<>0 then begin R:=4.6; end; Main.Rbutton.visible:=true; Main.REdit.visible:=true; Main.REdit.Value:=R; end; savedirectory:=mainpath+savedirectory; Main.SaveDialog.InitialDir:=savedirectory; DimMatrix(XX, DATASIZE, 4); DimVector(YY, DATASIZE); DimVector(Ycalc, DATASIZE); DimVector(XXn, DATASIZE); DimVector(B, 4); DimMatrix(V, 4, 4); end; procedure savefilep; var f:Text; i:longint; begin Main.SaveDialog.InitialDir:=savedirectory; if not Main.SaveDialog.Execute then exit; savefile:=Main.SaveDialog.FileName; {$I-} ioresult; assign(f,savefile); rewrite(f); writeln(f,'R= '+floatTostrF(R,ffFixed,10,3)); writeln(f,'%Time T T_out T_c U_out'); for i:=1 to datanum-1 do begin write(f,data_list[i].mtime:14:6); write(f,data_list[i].T:14:6); write(f,data_list[i].T_out:14:6); write(f,data_list[i].Tc:14:6); writeln(f,data_list[i].uout:14:6); end; close(f); saverequest:=false; end; procedure savequestion; begin if saverequest then begin if Application.MessageBox('Measurement is not saved! Save?', 'Save', MB_ICONQUESTION + MB_YESNO)=IDYES then savefilep; end; saverequest:=false; end; procedure Tmain.QuitButtonClick(Sender: TObject); begin savequestion; manualb:=true; if not evalueb then sendUSB('HRESET'); halt; end; procedure Tmain.SaveimageButtonClick(Sender: TObject); var year,month,day,dayw:word; hour,minute,second,sec100: word; Times,imagefile:String; begin {$I-} ioresult; getdate(year,month,day,dayw); gettime(hour,minute,second,sec100); times:=IntToStr(year)+'_'+IntToStr(month)+ '_'+IntToStr(day)+':'+IntToStr(hour)+'_'+IntToStr(minute)+'_'; imagefile:=imagedirectory+times+IntToStr(imagenum+1)+'_image.jpg'; inc(imagenum); ioresult; Main.TempChart.SaveToFile(TJPEGImage,imagefile); {$I+} end; procedure Add_draw(x:data_t); begin if (x.T>=main.tempminedit.Value) and (x.T<=main.tempmaxedit.Value) and (x.mtime<=main.timeedit.Value) then Main.TempChartLineseries.AddXY(x.mtime,x.T); end; procedure readUSB; var s:string; code:longint; i,j:longint; s1,s2,s3:string; d:double; integral:double; begin if evalueb then exit; case timepointer of 0: sendUSB( 'GETDATA'); 1: begin s:=getUSB(5000); if s<>'Data' then repeat s:=getUSB(500); writeln(s); until s='End'; if s='End' then exit; s:=getUSB(500); val(s,curdata.uout_set); s:=getUSB(500); val(s,curdata.uout,code); s:=getUSB(500); val(s,curdata.T_target,code); s:=getUSB(500); val(s,curdata.Tc,code); s:=getUSB(500); val(s,curdata.T,code); s:=getUSB(500); val(s,curdata.T_out,code); s:=getUSB(500); val(s,curdata.power,code); s:=getUSB(500); val(s,curdata.mtime,code); s:=getUSB(500); main.Tempheater.caption:='T heater='+floatTostrF(curdata.Tc,ffFixed,10,3)+' °C'; main.Uout.caption:='U='+floatTostrF(curdata.uout,ffFixed,10,3)+' V'; main.T.caption:='T='+floatTostrF(curdata.T,ffFixed,10,3)+' °C'; main.T0Edit.caption:='T_out='+floatTostrF(curdata.T_out,ffFixed,10,3)+' °C'; main.poweredit.caption:='U_power='+floatTostrF(curdata.power,ffFixed,10,3)+' V'; main.timeeditbox.caption:='t='+floatTostrF(curdata.mtime,ffFixed,10,1)+' s'; end; end; inc(timepointer); if timepointer>3 then timepointer:=0; end; procedure StartClock; begin GetTime(hours, minutes, seconds, milliseconds); end; function StopClock:word; var seconds_count : longint; c_hours: word; c_minutes: word; c_seconds: word; c_milliseconds: word; begin GetTime(c_hours, c_minutes, c_seconds, c_milliseconds); seconds_count := c_seconds - seconds + (c_minutes - minutes) * 60 + (c_hours - hours) * 3600; stopclock:=seconds_count; end; procedure Tmain.TimerTimer(Sender: TObject); begin if notconnected then begin exit; end; if not connected then begin Showmessage('Cannot connect to USB'); notconnected:=true; //halt; end; if connectform.visible then connectform.visible:=false; readUSB; if running and (curdata.mtime>0) and (timepointer=1) then begin inc(datanum); if datanum>=DATASIZE then datanum:=DATASIZE-1; data_list[datanum]:=curdata; Add_draw(data_list[datanum]); if uoutrunning then begin mtime:=curdata.mtime-mtime_0; main.mtimeedit.caption:='t='+floatTostrF(mtime,ffFixed,10,3)+' s'; end; end; end; procedure Tmain.UoutButtonClick(Sender: TObject); begin if manualb then exit; if evalueb then exit; if uoutrunning then begin uoutrunning:=false; sendUSB('UOUTSTART 0'); main.UoutButton.color:=clSilver; end else begin if not running then exit; sendUSB('UOUT '+floatTostrF(main.Uedit.Value,ffFixed,10,3)); uoutrunning:=true; running:=true; sendUSB('UOUTSTART 1'); Main.StartButton.Caption:='Stop'; main.UoutButton.color:=clRed; mtime_0:=curdata.mtime; end end; procedure Tmain.FormCreate(Sender: TObject); begin initvalues; if evalueb then exit; if paramcount>0 then main.command.visible:=true; if startUSB<0 then begin connected:=false; main.Timer.Enabled:=true; exit; end; connected:=true; main.Timer.Enabled:=true; manualb:=false; sendUSB('MANUAL 0'); sendUSB('UOUT 0'); sendUSB('TTARGET 18'); end; procedure Tmain.TempheaterEditKeyPress(Sender: TObject; var Key: char); begin if manualb then exit; if byte(key) =13 then begin if main.Tempheateredit.Value> main.Tempheateredit.MaxValue then main.Tempheateredit.Value:=main.Tempheateredit.MaxValue; sendUSB('TTARGET '+floatTostrF(main.Tempheateredit.Value,ffFixed,10,3)); end; end; procedure Tmain.TempheaterEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if manualb then exit; if main.Tempheateredit.Value> main.Tempheateredit.MaxValue then main.Tempheateredit.Value:=main.Tempheateredit.MaxValue; sendUSB('TTARGET '+floatTostrF(main.Tempheateredit.Value,ffFixed,10,3)); end; procedure Tmain.ChartToolsetDataPointDragToolDrag(ASender: TDataPointDragTool; var AGraphPoint: TDoublePoint); var y:double; begin y:= AGraphPoint.y; AGraphPoint.y:=y; if ASender <> ChartToolsetDataPointDragTool then exit; end; procedure Tmain.CommandKeyPress(Sender: TObject; var Key: char); begin if byte(key) =13 then begin sendUSB(command.Text); end; end; function RegFunc(X : Float; B : TVector) : Float; begin RegFunc:=B[1]*exp(-B[2]*x)+B[3]; end; procedure DerivProc(X, Y : Float; B, D : TVector); begin if y<-1e-10 then exit; D[1]:=exp(-B[2]*x); D[2]:=-x*B[1]*exp(-B[2]*x); D[3]:=1; end; procedure getinterval; var i:longint; begin n0:=1; while (data_list[n0].mtimen1 then begin i:=n0; n0:=n1; n1:=i; end; end; procedure Tmain.FitexpButtonClick(Sender: TObject); var i,j:longint; N:longint; Maxiter:longint=1000; Tol:Float=1e-8; begin if datanum=0 then exit; if main.FitexpButton.Caption='Fit exp.' then //if Application.MessageBox('Have you fitted the linear line?','', MB_ICONQUESTION + MB_YESNO)<>IDYES then exit; if not linedone then begin showmessage('Run "Fit linear" first!'); exit; end; main.ChartConstantLine1.Active:=true; main.ChartConstantLine2.Active:=true; if main.FitexpButton.Caption='Fit exp.' then begin main.FitexpButton.Caption:='Select interval'; main.LinFuncSeries.Active:=false; main.ExpFuncSeries.Active:=false; main.baseFuncSeries.Active:=false; main.FitexpButton.Color:=clRed; //main.ChartConstantLine1.Position:=0.1*main.TempChart.AxisList[1].Range.Max; //main.ChartConstantLine2.Position:=0.9*main.TempChart.AxisList[1].Range.Max; main.ChartConstantLine1.Position:=texp1; main.ChartConstantLine2.Position:=texp2; basefitb:=false; linfitb:=false; expfitb:=false; intb:=false; end else begin main.FitexpButton.Caption:='Fit exp.'; main.FitexpButton.Color:=clSilver; getinterval; texp1:=data_list[n0].mtime; texp2:=data_list[n1].mtime; N:=n1-n0; for i:=1 to N do begin XXn[i]:=data_list[i+n0].mtime; YY[i]:=data_list[i+n0].T; end; SetParamBounds(1, 0.01, 1000); SetParamBounds(2, 0, 1e12); SetParamBounds(3, 0.01, 1000); if data_list[n0+N].T_outIDYES then exit; if not basedone then begin showmessage('Run "Fit base" first!'); exit; end; main.ChartConstantLine1.Active:=true; main.ChartConstantLine2.Active:=true; if main.FitlinButton.Caption='Fit linear' then begin main.FitlinButton.Caption:='Select interval'; main.baseFuncSeries.Active:=false; main.LinFuncSeries.Active:=false; main.ExpFuncSeries.Active:=false; main.FitlinButton.Color:=clRed; length:=(main.TempChart.AxisList[1].Range.Max-main.TempChart.AxisList[1].Range.Min); main.ChartConstantLine1.Position:=0.1*length+main.TempChart.AxisList[1].Range.Min; main.ChartConstantLine2.Position:=0.2*length+main.TempChart.AxisList[1].Range.Min; basefitb:=false; linfitb:=false; expfitb:=false; intb:=false; end else begin main.FitlinButton.Caption:='Fit linear'; main.FitlinButton.Color:=clSilver; getinterval; N:=n1-n0; for i:=1 to N do begin XX[i,1]:=data_list[n0+i-1].mtime; XX[i,2]:=1; YY[i]:=data_list[n0+i-1].T; end; MulFit(XX, YY, 1, N, 2, false, B, V); a:=B[1]; T_zero:=B[2];U_h:=data_list[(n0+n1) div 2].uout; da:=sqrt(abs(V[1,1])); dT_zero:=sqrt(abs(V[2,2])); if (abs(a-a0)>1e-10) and (not linedone) then begin C_p_base:=U_h*U_h/R/(a-a0); dC_p:=0; end; if abs(a-a0)>1e-10 then begin C_p:=U_h*U_h/R/(a-a0); dC_p:=abs(C_p/(a-a0)*da); end; if linedone then if Application.MessageBox('Do you want to use the new parameters in the further calculations?','', MB_ICONQUESTION + MB_YESNO)=IDYES then begin c_p_base:=C_p; dC_p:=abs(C_p/(a-a0)*da); end; linfitb:=true; linedone:=true; main.LinFuncSeries.Active:=true; end; end; procedure Tmain.IntButtonClick(Sender: TObject); var i,N:longint; begin if datanum=0 then exit; if main.IntButton.Caption='Integral' then //if Application.MessageBox('Have you determined the parameters of the calorimeter?', '', MB_ICONQUESTION + MB_YESNO)<>IDYES then exit; if (not basedone) or (not linedone) then begin showmessage('The parameters of the calorimeter are not determined!'); exit; end; if not expdone then begin showmessage('Run "Fit exp" first!'); exit; end; main.ChartConstantLine1.Active:=true; main.ChartConstantLine2.Active:=true; if main.IntButton.Caption='Integral' then begin main.IntButton.Caption:='Select interval'; main.baseFuncSeries.Active:=false; main.LinFuncSeries.Active:=false; main.ExpFuncSeries.Active:=false; main.IntButton.Color:=clRed; //main.ChartConstantLine1.Position:=0.1*main.TempChart.AxisList[1].Range.Max; //main.ChartConstantLine2.Position:=0.9*main.TempChart.AxisList[1].Range.Max; main.ChartConstantLine1.Position:=tint1; main.ChartConstantLine2.Position:=tint2; basefitb:=false; linfitb:=false; expfitb:=false; intb:=false; end else begin main.IntButton.Caption:='Integral'; main.IntButton.Color:=clSilver; getinterval; N:=n1-n0; int:=0; tint1:=data_list[n0].mtime; tint2:=data_list[n1].mtime; for i:=1 to N-1do begin int:=int+(data_list[n0+i].T-data_list[n0+i].T_out)* (data_list[n0+i+1].mtime-data_list[n0+i].mtime); end; t1:=data_list[n0].mtime; t_inft:=data_list[n1].mtime; T_t:=data_list[n1].T; T_cham:=data_list[n0].Tc; deltaT:=data_list[n1].T-data_list[n0].T; Q:=c_p_base*deltaT+alpha_base*int; intb:=true; main.TempChart.AxisList[0].Range.Max:= main.TempChart.AxisList[0].Range.Max+0.001; end; end; function linfunc(x:double):double; begin linfunc:=a*x+T_zero; end; function basefunc(x:double):double; begin basefunc:=a0*x+T0; end; function expfunc(x:double):double; begin expfunc:=T_0*exp(-beta*x)+T_out; end; procedure Tmain.LinFuncSeriesCalculate(const AX: Double; out AY: Double); begin AY:=linfunc(AX); end; procedure Tmain.BaseFuncSeriesCalculate(const AX: Double; out AY: Double); begin AY:=basefunc(AX); end; procedure Tmain.REditKeyPress(Sender: TObject; var Key: char); begin if byte(key) =13 then R:=main.REdit.Value; end; procedure Tmain.REditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin R:=main.REdit.Value; end; procedure redraw; var i:longint; begin for i:=1 to datanum-1 do begin add_draw(data_list[i]); end; end; procedure minmax; var i:longint; min:double =500; max:double =-500; begin for i:=1 to datanum-1 do begin if data_list[i].Tmax then max:=data_list[i].T; end; max:=max+0.1; min:=min-0.1; main.Tempmaxedit.value:=max; main.TempChart.AxisList[0].Range.Max:=main.Tempmaxedit.value; main.Tempminedit.value:=min; main.TempChart.AxisList[0].Range.Min:=main.Tempminedit.value; end; procedure loaddraw; var p:text; i:longint; code:integer; var s:string; begin {$I-} ioresult; assign(p,Main.OpenDialog.FileName); reset(p); readln(p,s); s:=copy(s,4,20); val(s,R,code); main.REdit.Value:=R; readln(p,s); i:=0; repeat inc(i); read(p,data_list[i].mtime); read(p,data_list[i].T); read(p,data_list[i].T_out); read(p,data_list[i].Tc); readln(p,data_list[i].Uout); until eof(p); close(p); datanum:=i; minmax; timemax:=1.05*data_list[i-1].mtime; main.Timeedit.value:=timemax; main.TempChart.AxisList[1].Range.Max:=main.Timeedit.value; texp1:=0.1*main.TempChart.AxisList[1].Range.Max; texp2:=0.9*main.TempChart.AxisList[1].Range.Max; tint1:=texp1; tint2:=texp2; main.TempChartLineSeries.Clear; redraw; if evalueb then begin curdata:=data_list[datanum-1]; main.Tempheater.caption:='T heater='+floatTostrF(curdata.Tc,ffFixed,10,3)+' °C'; main.Uout.caption:='U='+floatTostrF(curdata.uout,ffFixed,10,3)+' V'; main.T.caption:='T='+floatTostrF(curdata.T,ffFixed,10,3)+' °C'; main.T0Edit.caption:='T_out='+floatTostrF(curdata.T_out,ffFixed,10,3)+' °C'; main.poweredit.caption:='U_power='+floatTostrF(curdata.power,ffFixed,10,3)+' V'; main.timeeditbox.caption:='t='+floatTostrF(curdata.mtime,ffFixed,10,1)+' s'; main.mtimeedit.caption:='t='+floatTostrF(curdata.mtime,ffFixed,10,1)+' s'; end; {$I+} end; procedure Tmain.RedrawButtonClick(Sender: TObject); begin if running then exit; savequestion; Main.OpenDialog.InitialDir:=savedirectory; Main.OpenDialog.Execute; if Main.OpenDialog.Filename = '' then exit; main.baseFuncSeries.Active:=false; main.LinFuncSeries.Active:=false; main.ExpFuncSeries.Active:=false; main.ChartConstantLine1.Active:=false; main.ChartConstantLine2.Active:=false; basefitb:=false; linfitb:=false; expfitb:=false; intb:=false; loaddraw; end; procedure Tmain.TempChartAfterDraw(ASender: TChart; ADrawer: IChartDrawer); var x0,y0,dy,dx,x,y:longint; scale:longint=1; s:string; begin if (not basefitb) and(not linfitb) and (not expfitb) and (not intb) then exit; //if printscale then scale:=3; x0:=scale*100;y0:=scale*20; x:=x0;y:=y0; dx:=TempChart.Width div 2+10; dy:=round(1.5*ADrawer.TextExtent('A',tfhtml).y); ADrawer.SetFont(TempChart.Title.Font); if basefitb then begin x:=x0; y:=y0; s:='azero'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(a0,ffGeneral,4,0); ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(da0,ffGeneral,2,0)+' °C/s'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; end; if linfitb then begin x:=x0; y:=y0; s:='T(t)=at+Tzero'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y0; x:=x0+dx; s:='Cp=Up2/(Ra)'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x0; y:=y+dy; s:='a'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(a,ffGeneral,4,0); ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(da,ffGeneral,2,0)+' °C/s'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y; x:=x0+dx; s:='Tzero= '+floattostrf(T_zero,ffGeneral,4,0); ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(dT_zero,ffGeneral,2,0)+' °C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y+dy; x:=x0; s:='Cp= '+floattostrf(C_p,ffGeneral,4,0); ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(dC_p,ffGeneral,2,0)+' J/°C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; end; if expfitb then begin x:=x0; s:='T(t)=Tb exp(-'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='&beta'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='t)+Tout'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x0+dx; y:=y; s:='&beta'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(beta,ffGeneral,4,0); ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(dbeta,ffGeneral,2,0)+' 1/s'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y+dy; x:=x0; s:='Tb= '+floattostrf(T_0,ffGeneral,4,0); ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(dT_0,ffGeneral,2,0)+' °C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y; x:=x0+dx; s:='Tout= '+floattostrf(T_out,ffGeneral,4,0); //s:=s+' °C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(dT_out,ffGeneral,2,0)+' °C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y+dy; x:=x0; s:='&alpha'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='&beta'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='Cp'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; y:=y; x:=x0+dx; s:='&alpha'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(alpha,ffGeneral,4,0); ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='±'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(dalpha,ffGeneral,2,0)+' W/°C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; end; if intb then begin x:=x0; s:='I='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='&int'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='t0t[T(t)-Tout]dt'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x0+dx; y:=y; s:='I='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(int,ffGeneral,4,0)+' °Cs'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y+dy; x:=x0; s:='t0='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(T1,ffGeneral,4,0); s:=s+' s, t='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(T_inft,ffGeneral,4,0)+' s, Tm='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(T_cham,ffGeneral,4,0)+' °C, T(t)='+floattostrf(T_t,ffGeneral,4,0)+' °C,' ; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y; x:=x0+dx; s:='&Delta'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='T=T(t)-T(t0)='+floattostrf(deltaT,ffGeneral,4,0); s:=s+' °C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y+dy; x:=x0; s:='Q=Cp[T(t)-T(t0)]+'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='&alpha'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='I'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; y:=y; x:=x0+dx; s:='Q='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(Q,ffGeneral,4,0)+' W, Cm='; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:=floattostrf(Q/(T_cham-T_t),ffGeneral,4,0)+' J/°C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; end; end; procedure Tmain.TempheaterButtonClick(Sender: TObject); begin if manualb then exit; if evalueb then exit; if main.Tempheateredit.Value> main.Tempheateredit.MaxValue then main.Tempheateredit.Value:=main.Tempheateredit.MaxValue; sendUSB('TTARGET '+floatTostrF(main.Tempheateredit.Value,ffFixed,10,3)); end; procedure Tmain.TempminEditChange(Sender: TObject); begin end; procedure Tmain.ExpFuncSeriesCalculate(const AX: Double; out AY: Double); begin Ay:=expfunc(AX); end; procedure Tmain.UEditChange(Sender: TObject); begin if manualb then exit; sendUSB('UOUT '+floatTostrF(main.Uedit.Value,ffFixed,10,3)); end; procedure Tmain.ChartToolsetDataPointDragToolAfterMouseUp(ATool: TChartTool; APoint: TPoint); begin end; procedure setTimemax; var y0,y1:double; begin main.TempChartLineSeries.Clear; main.TempChart.AxisList[1].Range.Max:=main.Timeedit.value; texp1:=0.1*main.TempChart.AxisList[1].Range.Max; texp2:=0.9*main.TempChart.AxisList[1].Range.Max; tint1:=texp1; tint2:=texp2; end; procedure setTmax; begin main.TempChartLineSeries.Clear; if main.Tempmaxedit.value<=main.Tempminedit.value then main.Tempmaxedit.value:=main.Tempminedit.value+0.001; main.TempChart.AxisList[0].Range.Min:=main.Tempminedit.value; main.TempChart.AxisList[0].Range.Max:=main.Tempmaxedit.value; end; procedure setTmin; begin main.TempChartLineSeries.Clear; if main.Tempminedit.value>=main.Tempmaxedit.value then main.Tempminedit.value:=main.Tempmaxedit.value-0.001; main.TempChart.AxisList[0].Range.Min:=main.Tempminedit.value; main.TempChart.AxisList[0].Range.Max:=main.Tempmaxedit.value; end; procedure Tmain.TempmaxEditKeyPress(Sender: TObject; var Key: char); begin if byte(key) =13 then begin setTmax; redraw; end; end; procedure Tmain.TempmaxEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin main.TempChart.AxisList[0].Range.Max:=main.Tempmaxedit.value; setTmax; redraw; end; procedure Tmain.TempminEditKeyPress(Sender: TObject; var Key: char); begin if byte(key) =13 then begin setTmin; redraw; end; end; procedure Tmain.TempminEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if main.TempChart.AxisList[0].Range.Min=main.Tempminedit.value then exit; setTmin; redraw; end; procedure Tmain.TimeEditKeyPress(Sender: TObject; var Key: char); begin if byte(key) =13 then begin setTimemax; redraw; end; end; procedure Tmain.TimeEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if main.TempChart.AxisList[1].Range.Max=main.Timeedit.value then exit; setTimemax; redraw; end; procedure Tmain.Timer1Timer(Sender: TObject); begin Timer1.Enabled:=false; if evalueb then begin connectform.visible:=false; manualbutton.visible:=false; startbutton.visible:=false; tempheaterEdit.visible:=false; UEdit.visible:=false; powerEdit.visible:=false; //mtimeEdit.visible:=false; end; Main.SelectDirectoryDialog.InitialDir:=mainpath+'measures'+bbs; Main.SelectDirectoryDialog.Execute; savedirectory:=Main.SelectDirectoryDialog.FileName+bbs; //writeln(savedirectory); imagedirectory:=Main.SelectDirectoryDialog.FileName+bbs; end; procedure Tmain.StartButtonClick(Sender: TObject); var i:longint=0; y0,y1:double; begin if running then begin running:=false; main.Startbutton.caption:='Start'; sendUSB('START 0'); end else begin savequestion; running:=true; texp1:=0.1*main.TempChart.AxisList[1].Range.Max; texp2:=0.9*main.TempChart.AxisList[1].Range.Max; tint1:=texp1; tint2:=texp2; main.Startbutton.caption:='Stop'; TempChartLineSeries.Active:=true; TempChartLineSeries.clear; main.baseFuncSeries.Active:=false; main.ChartConstantLine1.Active:=false; main.ChartConstantLine2.Active:=false; main.LinFuncSeries.Active:=false; main.ExpFuncSeries.Active:=false; datanum:=0; sendUSB('START 1'); saverequest:=true; basefitb:=false; linfitb:=false; expfitb:=false; intb:=false; end; end; procedure Tmain.SaveButtonClick(Sender: TObject); begin saverequest:=false; savefilep; end; procedure Tmain.FormClose(Sender: TObject; var CloseAction: TCloseAction); begin savequestion; manualb:=true; if not evalueb then sendUSB('RESET'); halt; end; procedure Tmain.UEditKeyPress(Sender: TObject; var Key: char); begin if manualb then exit; if byte(key) =13 then sendUSB('UOUT '+floatTostrF(main.Uedit.Value,ffFixed,10,3)); end; procedure Tmain.UEditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin sendUSB('UOUT '+floatTostrF(main.Uedit.Value,ffFixed,10,3)); end; procedure Tmain.ManualButtonClick(Sender: TObject); begin if manualb then begin manualb:=false; main.manualButton.caption:='Remote'; sendUSB('MANUAL 0'); sendUSB('UOUTSTART 0'); //main.coilCurrentButton.color:=clSilver; //main.hallCurrentButton.color:=clSilver; end else begin manualb:=true; main.manualButton.caption:='Manual'; sendUSB('MANUAL 1'); //main.CoilcurrentButton.color:=clWhite; //main.hallcurrentButton.color:=clWhite; end; end; procedure paramout; var code:longint; d:double; s:string; begin if paramcount()>1 then begin if paramstr(1)='SETTEMP' then begin val(paramstr(2),d,code); if code=0 then begin s:=paramstr(1)+' '+paramstr(2); writeln('send: '+s); sendUSB(s); end; end; end; end; end.