unit mainunit; //{$mode objfpc}{$H+} {$mode delphi} {$H+} //{$define evalue} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, CustomDrawnControls, Spin, StdCtrls, ExtCtrls, PrintersDlgs, TAGraph, TATransformations, TASeries, Dos,Process, TAChartUtils, TADrawUtils, TATools, LCLType, TAChartAxisUtils, TACustomSource, TATypes, TAFuncSeries, Types; type { Tmain } Tmain = class(TForm) ChartConstantLine1: TConstantLine; ChartConstantLine2: TConstantLine; ChartToolset: TChartToolset; ChartToolsetDataPointDragTool: TDataPointDragTool; Command: TEdit; ExpFuncSeries: TFuncSeries; LinFuncSeries: TFuncSeries; currentButton1: TCDButton; currentedit1: TFloatSpinEdit; FitexpButton: TCDButton; FitlinButton: TCDButton; OpenDialog: TOpenDialog; PE_SBmode: TCDButton; PEmode: TCDButton; RedrawButton: TCDButton; SelectDirectoryDialog: TSelectDirectoryDialog; T1Text: TStaticText; Text1: TStaticText; Text2: TStaticText; thermo_TempLineSeries: TLineSeries; thermoConstantLine: TConstantLine; Timer1: TTimer; xmodeButton: TCDButton; Temp_TimeLineSeries: TLineSeries; thermo_TimeLineSeries: TLineSeries; dLLinearAxisTrans: TLinearAxisTransform; TempLinearAxisTrans: TLinearAxisTransform; TimeLinearAxisTrans: TLinearAxisTransform; TempAxisTrans: TChartAxisTransformations; dLAxisTrans: TChartAxisTransformations; TimeAxiTsrans: TChartAxisTransformations; CurrentText: TStaticText; T2Text: TStaticText; Chart: TChart; dLeditmax: TFloatSpinEdit; currentedit: TFloatSpinEdit; dLeditmin: TFloatSpinEdit; PrintDialog: TPrintDialog; SaveDialog: TSaveDialog; currentButton: TCDButton; SBmode: TCDButton; manual: TCDButton; Tempeditmax: TFloatSpinEdit; Timeeditmin: TFloatSpinEdit; Save: TCDButton; Image: TCDButton; Print: TCDButton; Quit: TCDButton; Temperature: TCDButton; ThermoButton: TCDButton; Time: TCDButton; Timeeditmax: TFloatSpinEdit; Tempeditmin: TFloatSpinEdit; Timer: TTimer; TimeText: TStaticText; TempText: TStaticText; thermofText: TStaticText; coursortext: TStaticText; procedure ChartAfterDraw(ASender: TChart; ADrawer: IChartDrawer); procedure ChartMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ChartMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ChartToolsetDataPointDragToolAfterMouseUp(ATool: TChartTool; APoint: TPoint); procedure ChartToolsetDataPointDragToolDrag(ASender: TDataPointDragTool; var AGraphPoint: TDoublePoint); procedure CommandKeyPress(Sender: TObject; var Key: char); procedure currentButtonClick(Sender: TObject); procedure dLeditmaxKeyPress(Sender: TObject; var Key: char); procedure dLeditmaxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure dLeditminKeyPress(Sender: TObject; var Key: char); procedure dLeditminMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ExpFuncSeriesCalculate(const AX: Double; out AY: Double); procedure FitexpButtonClick(Sender: TObject); procedure FitlinButtonClick(Sender: TObject); procedure FormActivate(Sender: TObject); procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure LinFuncSeriesCalculate(const AX: Double; out AY: Double); procedure PEmodeClick(Sender: TObject); procedure PE_SBmodeClick(Sender: TObject); procedure RedrawButtonClick(Sender: TObject); procedure Text1Click(Sender: TObject); procedure ThermoButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FormCreate(Sender: TObject); procedure ImageClick(Sender: TObject); procedure manualClick(Sender: TObject); procedure currenteditKeyPress(Sender: TObject; var Key: char); procedure currenteditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure PrintClick(Sender: TObject); procedure QuitClick(Sender: TObject); procedure SaveClick(Sender: TObject); procedure SBmodeClick(Sender: TObject); procedure TempeditmaxChange(Sender: TObject); procedure TempeditmaxKeyPress(Sender: TObject; var Key: char); procedure TempeditmaxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TempeditminKeyPress(Sender: TObject; var Key: char); procedure TempeditminMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TemperatureMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TimeeditmaxKeyPress(Sender: TObject; var Key: char); procedure TimeeditmaxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TimeeditminKeyPress(Sender: TObject; var Key: char); procedure TimeeditminMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TimeMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Timer1Timer(Sender: TObject); procedure TimerTimer(Sender: TObject); procedure xmodeButtonClick(Sender: TObject); private public end; type data_t=record thermof:double; current:double; T1:double; T2:double; dT:double; time:double; end; const DATASIZE=10000; var main: Tmain; procedure paramout; implementation uses OSPrinters, Printers, TAPrint,comusb, math, utypes,umulfit,unlfit,ufft, connect; {$R *.lfm} { Tmain } var timemin:double=0; timemax:double=250; timescale:double=1; timeoffset:double=0; tempmin:double=-50; tempmax:double=5; tempscale:double=1; tempoffset:double=0; thermomin:double=-200; thermomax:double=200; thermoscale:double=1; thermooffset:double=0; running:boolean=false; oldrunning:boolean=false; saverequest:boolean; manualb:boolean=true; mainpath:string; {$ifdef LINUX} imagedirectory:string='measures/'; savedirectory:string='measures/'; bbs:string='/'; {$else} imagedirectory:string='measures\'; savedirectory:string='measures\'; bbs:string='\'; {$endif} imagefile:string; imagenum:longint; printerselected:boolean=false; curdata:data_t; data_list:array[0..DATASIZE] of data_t; datanum:longint; mode:longint; mode_r:longint=0; modeb:boolean=false; modepointer:longint=0; timepointer:longint=0; c1,c2,cp,clock:array [0..256] of double; xmode:boolean; seebeckrunning:boolean=false; peltierrunning:boolean=false; peltierm:boolean=true; connected:boolean=false; notconnected:boolean=false; XX : TMatrix; YY : TVector; XXn : TVector; B : TVector; V : TMatrix; n0,n1:longint; linfitb:boolean=false; expfitb:boolean=false; a,zero,beta,T_0,T_inf:double; da,dzero,dbeta,dT_0,dT_inf:double; {$ifdef evalue} evalueb:boolean=true; {$else} evalueb:boolean=false; {$endif} function get_instdir:string; var ss,sss:string; begin ss:=paramstr(0); {$IFDEF LINUX} sss:=copy(ss,1,pos('peltier',ss)-1)+'peltier/'; mainpath:=getuserdir; //+'peltier/'; {$ELSE} mainpath:=copy(ss,1,pos('peltier.exe',ss)-1); sss:=mainpath; {$ENDIF} imagedirectory:=mainpath+imagedirectory; savedirectory:=mainpath+savedirectory; result:=sss; end; function Temp2R(T:double):double; var a:double=3.90830E-3; b:double=-5.77500E-7; c:double=-4.18301E-12; begin Temp2R:=100*(1+a*T+b*T*T+(100-T)*c*T*T*T); end; procedure create_r2t; var f:text; i:longint; t:double; begin assign(f,'./r2T.dat'); rewrite(f); for i:=-20 to 10 do begin t:=i*10; writeln(f,Temp2r(t),' ',t); end; close(f) end; function tempconv(x:double):double; var t:double; begin t:=tempscale*x+tempoffset; if t<0 then t:=0; if t>1 then t:=1; result:=t; end; function timeconv(x:double):double; var t:double; begin t:=timescale*x+timeoffset; if t<0 then t:=0; if t>1 then t:=1; result:=t; end; function thermoconv(x:double):double; var t:double; begin t:=thermoscale*x+thermooffset; if t<0 then t:=0; if t>1 then t:=1; result:=t; end; procedure Add_draw(x:data_t); begin Main.thermo_TimeLineseries.AddXY(Timeconv(x.time),thermoconv(x.thermof)); Main.Temp_TimeLineseries.AddXY(Timeconv(x.time),Tempconv(x.dT)); Main.thermo_TempLineseries.AddXY(Tempconv(x.dT),thermoconv(x.thermof)); end; procedure clearlines; begin main.ChartConstantLine1.Active:=false; main.ChartConstantLine2.Active:=false; main.LinFuncSeries.Active:=false; main.ExpFuncSeries.Active:=false; linfitb:=false; expfitb:=false; end; procedure cleandraw; var i:longint; begin Main.thermo_TimeLineseries.clear; Main.Temp_TimeLineseries.clear; Main.thermo_TempLineseries.clear; for i:=1 to datanum-1 do Add_draw(data_list[i]); end; procedure settimemax; begin timemax:=main.timeeditmax.value; main.timeeditmin.maxvalue:=timemax-1e-6; timescale:=1.0/(timemax-timemin); timeoffset:=-timescale*timemin; main.TimeLinearAxisTrans.Offset:=timeoffset; main.TimeLinearAxisTrans.scale:=timescale; end; procedure Tmain.TimeeditmaxKeyPress(Sender: TObject; var Key: char); begin if byte(key)=13 then begin settimemax; cleandraw; end; end; procedure Tmain.TimeeditmaxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if timemax=main.timeeditmax.value then exit; settimemax; cleandraw; end; procedure settimemin; begin timemin:=main.timeeditmin.value; main.timeeditmax.minvalue:=timemin+1e-6; timescale:=1.0/(timemax-timemin); timeoffset:=-timescale*timemin; main.TimeLinearAxisTrans.Offset:=timeoffset; main.TimeLinearAxisTrans.scale:=timescale; end; procedure Tmain.TimeeditminKeyPress(Sender: TObject; var Key: char); begin if byte(key)=13 then begin settimemin; cleandraw; end; end; procedure Tmain.TimeeditminMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if timemin=main.timeeditmin.value then exit; settimemin; cleandraw; end; procedure Tmain.TimeMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var m,d:double; begin m:=(main.timeeditmin.value+main.timeeditmax.value)/2; d:=(main.timeeditmax.value-main.timeeditmin.value)/2; if Button=mbLeft then d:=d/2.0; if Button=mbRight then d:=d*2.0; if timemin>0 then timemin:=m-d; if timemin<0 then timemin:=0; timemax:=timemin+2*d; main.timeeditmin.value:=timemin; main.timeeditmax.value:=timemax; settimemin; settimemax; cleandraw; end; procedure Tmain.Timer1Timer(Sender: TObject); begin //paramout; Timer1.Enabled:=false; if evalueb then begin connectform.visible:=false; manual.visible:=false; SBmode.visible:=false; PEmode.visible:=false; currentbutton1.visible:=false; currentedit1.visible:=false; //currenttext.visible:=false; T1Text.visible:=false; //T2Text.visible:=false; redrawbutton.Left:=save.Left; redrawbutton.Top:=save.Top-48; end; Main.SelectDirectoryDialog.InitialDir:=mainpath+'measures'+bbs; Main.SelectDirectoryDialog.Execute; savedirectory:=Main.SelectDirectoryDialog.FileName+bbs; imagedirectory:=Main.SelectDirectoryDialog.FileName+bbs; 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.thermof,code); s:=getUSB(500); //writeln(s); val(s,curdata.current,code); s:=getUSB(500); val(s,curdata.T1,code); s:=getUSB(500); val(s,curdata.T2,code); s:=getUSB(500); val(s,curdata.dT,code); s:=getUSB(500); val(s,curdata.time,code); s:=getUSB(500); //writeln(s); val(s,mode,code); s:=getUSB(500); oldrunning:=running; case mode of 0:begin //main.SBmode.caption:='Seebek off'; //main.PEmode.caption:='Peltier off'; //running:=false; curdata.thermof:=0; end; 1:begin //main.SBmode.caption:='Seebek off'; //main.PEmode.caption:='Peltier off'; //running:=false; curdata.current:=0; end; 2:begin //main.SBmode.caption:='Seebek off'; //main.PEmode.caption:='Peltier on'; //running:=true; curdata.thermof:=0; end; 3:begin //main.SBmode.caption:='Seebek on'; //main.PEmode.caption:='Peltier off'; //running:=true; curdata.current:=0; end; end; if (not oldrunning) and running then begin datanum:=0; cleandraw; saverequest:=true; end; main.CurrentText.caption:='Current='+floatTostrF(curdata.current,ffFixed,10,2)+' A'; main.T2Text.caption:='T0='+floatTostrF(curdata.T2,ffFixed,10,3)+' °C'; main.T1Text.caption:='T='+floatTostrF(curdata.T1,ffFixed,10,3)+' °C'; main.TimeText.caption:='Time='+floatTostrF(curdata.time,ffFixed,10,2)+' s'; main.TempText.caption:='dT='+floatTostrF(curdata.dT,ffFixed,10,3)+' °C'; main.thermofText.caption:='UT='+floatTostrF(curdata.thermof,ffFixed,10,3)+' mV'; end; end; inc(timepointer); if timepointer>3 then timepointer:=0; end; procedure manual_remote; begin if manualb then begin manualb:=false; main.manual.caption:='Remote'; sendUSB('MANUAL 0'); sendUSB('THERMO 0'); main.PE_SBmode.caption:='Peltier'; sendUSB('CURRENT '+IntToStr(Trunc(main.currentedit.Value))); main.SBmode.color:=clSilver; main.PEmode.color:=clSilver; main.CurrentButton.color:=clSilver; end else begin manualb:=true; main.manual.caption:='Manual'; sendUSB('MANUAL 1'); main.SBmode.color:=clWhite; main.PEmode.color:=clWhite; main.CurrentButton.color:=clWhite; end; end; procedure Tmain.TimerTimer(Sender: TObject); begin if notconnected then exit; if not connected then begin Showmessage('Cannot connect to USB'); notconnected:=true; end; if connectform.Visible then connectform.Visible:=false; readUSB; if running and (curdata.time>0) and (timepointer=1) then begin inc(datanum); if datanum>=DATASIZE then datanum:=DATASIZE-1; data_list[datanum]:=curdata; Add_draw(data_list[datanum]); end; if modeb then inc(modepointer); if modepointer=2 then begin //case mode of //0:main.PTmode.caption:='Peltier'; //1:main.PTmode.caption:='Thermo'; //end; modeb:=false; modepointer:=0; end; end; procedure Tmain.xmodeButtonClick(Sender: TObject); begin if peltierrunning then exit; if (peltierm) then exit; clearlines; If xmode then begin xmode:=false; main.chart.AxisList[2].Visible:=true; main.chart.AxisList[3].Visible:=true; main.chart.AxisList[4].Visible:=true; main.chart.AxisList[5].Visible:=false; main.thermo_TempLineSeries.active:=false; main.Temp_TimeLineSeries.active:=true; main.thermo_TimeLineSeries.active:=true; end else begin xmode:=true; main.chart.AxisList[2].Visible:=true; main.chart.AxisList[3].Visible:=false; main.chart.AxisList[4].Visible:=false; main.chart.AxisList[5].Visible:=true; main.thermo_TempLineSeries.active:=true; main.Temp_TimeLineSeries.active:=false; main.thermo_TimeLineSeries.active:=false; end; end; procedure settempmin; begin tempmin:=main.tempeditmin.value; main.tempeditmax.minvalue:=tempmin-1e-6; tempscale:=1.0/(tempmax-tempmin); tempoffset:=-tempscale*tempmin; main.TempLinearAxisTrans.Offset:=tempoffset; main.TempLinearAxisTrans.scale:=tempscale; end; procedure Tmain.TempeditminKeyPress(Sender: TObject; var Key: char); begin if byte(key)=13 then begin settempmin; cleandraw; end; end; procedure Tmain.TempeditminMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if tempmin=main.tempeditmin.value then exit; settempmin; cleandraw; end; procedure settempmax; begin tempmax:=main.tempeditmax.value; main.tempeditmin.maxvalue:=tempmax-1e-6; tempscale:=1.0/(tempmax-tempmin); tempoffset:=-tempscale*tempmin; main.TempLinearAxisTrans.Offset:=tempoffset; main.TempLinearAxisTrans.scale:=tempscale; end; procedure Tmain.TempeditmaxKeyPress(Sender: TObject; var Key: char); begin if byte(key)=13 then begin settempmax; cleandraw; end; end; procedure Tmain.TempeditmaxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if tempmax=main.tempeditmax.value then exit; settempmax; cleandraw; end; procedure Tmain.TemperatureMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var m,d:double; begin m:=(main.tempeditmin.value+main.tempeditmax.value)/2; d:=(main.tempeditmax.value-main.tempeditmin.value)/2; if Button=mbLeft then d:=d/2.0; if Button=mbRight then d:=d*2.0; tempmin:=m-d; tempmax:=tempmin+2*d; main.tempeditmin.value:=tempmin; main.tempeditmax.value:=tempmax; settempmin; settempmax; cleandraw; end; procedure setthermomin; begin thermomin:=main.dLeditmin.value; main.dLeditmax.minvalue:=thermomin+1e-6; thermoscale:=1.0/(thermomax-thermomin); thermooffset:=-thermoscale*thermomin; main.dLLinearAxisTrans.Offset:=thermooffset; main.dLLinearAxisTrans.scale:=thermoscale; if (thermomax>0) and (thermomin<0) then main.thermoConstantLine.active:=true else main.thermoConstantLine.active:=false; end; procedure Tmain.dLeditminKeyPress(Sender: TObject; var Key: char); begin if byte(key)=13 then begin setthermomin; cleandraw; end; end; procedure Tmain.dLeditminMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if thermomin=main.dLeditmin.value then exit; setthermomin; cleandraw; end; procedure Tmain.FormActivate(Sender: TObject); begin end; procedure savep; var p:text; i:longint; begin if datanum=0 then exit; Main.SaveDialog.InitialDir:=savedirectory; Main.saveDialog.Execute; writeln(Main.SaveDialog.FileName); if Main.SaveDialog.Filename = '' then exit; {$I-} ioresult; assign(p,Main.SaveDialog.FileName); rewrite(p); if peltierm then writeln(p,'# Time [s] dTemp [°C] Temp [°C] Temp_0 [°C] I [A]') else writeln(p,'# Time [s] dTemp [°C] Temp [°C] Temp_0 [°C] U_T [mV]'); for i:=1 to datanum-1 do begin write(p,data_list[i].time:14:6); write(p,data_list[i].dT:14:6); write(p,data_list[i].T1:14:6); write(p,data_list[i].T2:14:6); if peltierm then writeln(p,data_list[i].current:14:6) else writeln(p,data_list[i].thermof:14:6); end; close(p); saverequest:=false; {$I+} end; procedure closep; begin if running then begin showmessage('Measure is on!'); exit; end; if saverequest then begin if Application.MessageBox('Measurement is not saved! Save?', 'Save', MB_ICONQUESTION + MB_YESNO)=IDYES then savep; end; if not evalueb then sendUSB('RESET'); halt; end; procedure Tmain.FormClose(Sender: TObject; var CloseAction: TCloseAction); begin closep; end; procedure setthermomax; begin thermomax:=main.dLeditmax.value; main.dLeditmin.maxvalue:=thermomax-1e-6; thermoscale:=1.0/(thermomax-thermomin); thermooffset:=-thermoscale*thermomin; main.dLLinearAxisTrans.Offset:=thermooffset; main.dLLinearAxisTrans.scale:=thermoscale; if (thermomax>0) and (thermomin<0) then main.thermoConstantLine.active:=true else main.thermoConstantLine.active:=false; end; procedure Tmain.dLeditmaxKeyPress(Sender: TObject; var Key: char); begin if byte(key)=13 then begin setthermomax; cleandraw; end; end; procedure Tmain.ChartMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var p: TDoublePoint; fs:string; timev,duv,tempv:double; begin p := Main.chart.ImageToGraph(Point(X,Y)); timev:=(P.X-timeoffset)/timescale; dUv:=(P.Y-thermooffset)/thermoscale; Tempv:=(P.Y-Tempoffset)/Tempscale; fs:='(Time= %.1f s, U_T %.3f mV, Temp %.1f C)'; Main.coursortext.caption:=Format(fs, [timev, duv, tempv]) end; procedure Tmain.ChartMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Main.coursortext.caption:=''; end; procedure Tmain.currentButtonClick(Sender: TObject); begin if manualb then exit; sendUSB('CURRENT '+floatTostrF(main.currentedit.Value*5.0/4.9,ffFixed,10,3)); end; procedure Tmain.dLeditmaxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if thermomax=main.dLeditmax.value then exit; setthermomax; cleandraw; end; procedure Tmain.ThermoButtonMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var m,d:double; begin m:=(main.dLeditmin.value+main.dLeditmax.value)/2; d:=(main.dLeditmax.value-main.dLeditmin.value)/2; if Button=mbLeft then d:=d/2.0; if Button=mbRight then d:=d*2.0; thermomin:=m-d; thermomax:=thermomin+2*d; main.dLeditmin.value:=thermomin; main.dLeditmax.value:=thermomax; setthermomin; setthermomax; cleandraw; end; procedure initvalues; begin //create_r2t; get_instdir; imagedirectory:=mainpath+imagedirectory; savedirectory:=mainpath+savedirectory; main.timeeditmax.value:=timemax; main.timeeditmin.value:=timemin; settimemin; settimemax; main.tempeditmax.value:=tempmax; main.tempeditmin.value:=tempmin; settempmin; settempmax; main.dLeditmax.value:=thermomax; main.dLeditmin.value:=thermomin; setthermomin; setthermomax; running:=false; saverequest:=false; xmode:=false; main.chart.AxisList[3].Visible:=true; main.chart.AxisList[4].Visible:=true; main.chart.AxisList[5].Visible:=false; main.thermo_TempLineSeries.active:=false; main.Temp_TimeLineSeries.active:=true; main.thermo_TimeLineSeries.active:=true; DimMatrix(XX, DATASIZE, 4); DimVector(YY, DATASIZE); DimVector(XXn, DATASIZE); DimVector(B, 4); DimMatrix(V, 4, 4); end; procedure Tmain.ImageClick(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.Chart.SaveToFile(TJPEGImage,imagefile); {$I+} 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; manual_remote; main.Timer.Enabled:=true; end; procedure Tmain.manualClick(Sender: TObject); begin if running then exit; manual_remote; end; procedure Tmain.currenteditKeyPress(Sender: TObject; var Key: char); begin if manualb then exit; if byte(key) =13 then sendUSB('CURRENT '+floatTostrF(main.currentedit.Value*5.0/4.9,ffFixed,10,3)); end; procedure Tmain.currenteditMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if manualb then exit; sendUSB('CURRENT '+floatTostrF(main.currentedit.Value*5.0/4.9,ffFixed,10,3)); end; procedure Tmain.PrintClick(Sender: TObject); var r: TRect; d: Integer; begin if not running then begin Main.PrintDialog.Execute; printerselected:=true; end; if not printerselected then begin Main.PrintDialog.Execute; printerselected:=true; end; Printer.BeginDoc; try d:=Printer.XDPI div 2; r := Rect(0, 0, Printer.PageWidth-d, Printer.PageHeight div 2); Main.Chart.Draw(TPrinterDrawer.Create(Printer, true), r); finally Printer.EndDoc; end; end; procedure Tmain.SaveClick(Sender: TObject); begin if saverequest then savep; end; procedure Tmain.QuitClick(Sender: TObject); begin closep; end; procedure Tmain.PEmodeClick(Sender: TObject); begin if manualb then exit; if main.SBmode.Caption='Seebeck on' then exit; if running then begin main.PEmode.Caption:='Peltier off'; sendUSB('CURRENT 0'); sendUSB('THERMO 0'); running:=false; if datanum>0 then saverequest:=true; peltierrunning:=false; end else begin if saverequest then begin if Application.MessageBox('Measurement is not saved! Save?', 'Save', MB_ICONQUESTION + MB_YESNO)=IDYES then savep; end; saverequest:=false; main.PEmode.Caption:='Peltier on'; PE_SBmode.caption:='Peltier'; clearlines; xmode:=false; main.chart.AxisList[2].Visible:=false; main.chart.AxisList[3].Visible:=true; main.chart.AxisList[3].Alignment:=calLeft; main.chart.AxisList[4].Visible:=true; main.chart.AxisList[5].Visible:=false; main.thermo_TempLineSeries.active:=false; main.Temp_TimeLineSeries.active:=true; main.thermo_TimeLineSeries.active:=false; sendUSB('CURRENT '+floatTostrF(main.currentedit1.Value,ffFixed,10,3)); sendUSB('THERMO 2'); peltierrunning:=true; datanum:=0; cleandraw; running:=true; peltierm:=true; end; end; procedure Tmain.PE_SBmodeClick(Sender: TObject); begin if manualb then exit; if running then exit; if PE_SBmode.caption='Peltier' then begin PE_SBmode.caption:='Thermo V'; sendUSB('THERMO 1'); end else begin PE_SBmode.caption:='Peltier'; sendUSB('THERMO 0'); end; end; procedure Tmain.Text1Click(Sender: TObject); begin end; procedure savequestion; begin if saverequest then begin if Application.MessageBox('Measurement is not saved! Save?', 'Save', MB_ICONQUESTION + MB_YESNO)=IDYES then savep; end; saverequest:=false; end; procedure Tmain.SBmodeClick(Sender: TObject); begin if manualb then exit; if main.PEmode.Caption='Peltier on' then exit; if running then begin main.SBmode.Caption:='Seeback off'; sendUSB('THERMO 1'); running:=false; if datanum>0 then saverequest:=true; seebeckrunning:=false; end else begin if saverequest then begin if Application.MessageBox('Measurement is not saved! Save?', 'Save', MB_ICONQUESTION + MB_YESNO)=IDYES then savep; end; saverequest:=false; clearlines; main.SBmode.Caption:='Seebeck on'; PE_SBmode.caption:='Thermo V'; xmode:=false; main.chart.AxisList[2].Visible:=true; main.chart.AxisList[3].Visible:=true; main.chart.AxisList[3].Alignment:=calRight; main.chart.AxisList[4].Visible:=true; main.chart.AxisList[5].Visible:=false; main.thermo_TempLineSeries.active:=false; main.Temp_TimeLineSeries.active:=true; main.thermo_TimeLineSeries.active:=true; PE_SBmode.caption:='Thermo V'; sendUSB('THERMO 3'); seebeckrunning:=true; peltierm:=false; datanum:=0; cleandraw; running:=true; end; end; procedure Tmain.TempeditmaxChange(Sender: TObject); begin 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; function linfunc(x:double):double; begin linfunc:=a*x+zero; end; function expfunc(x:double):double; begin expfunc:=T_0*exp(-beta*x)+T_inf; end; procedure Tmain.LinFuncSeriesCalculate(const AX: Double; out AY: Double); var x,y:double; begin x:=(AX-tempoffset)/tempscale; y:=linfunc(x); AY:=thermoconv(y); end; procedure Tmain.ExpFuncSeriesCalculate(const AX: Double; out AY: Double); var x,y:double; begin x:=(AX-timeoffset)/timescale; y:=expfunc(x); AY:=tempconv(y); end; procedure getinterval; var i:longint; begin n0:=1; while (timeconv(data_list[n0].time)n1 then begin i:=n0; n0:=n1; n1:=i; end; end; procedure getinterval_dt; var i:longint; begin n0:=1; while (tempconv(data_list[n0].dt)n1 then begin i:=n0; n0:=n1; n1:=i; end; end; procedure Tmain.FitlinButtonClick(Sender: TObject); var i,N:longint; begin if datanum=0 then exit; if peltierm then exit; clearlines; xmode:=true; main.chart.AxisList[2].Visible:=true; main.chart.AxisList[3].Visible:=false; main.chart.AxisList[4].Visible:=false; main.chart.AxisList[5].Visible:=true; main.thermo_TempLineSeries.active:=true; main.Temp_TimeLineSeries.active:=false; main.thermo_TimeLineSeries.active:=false; cleandraw; main.ChartConstantLine1.Active:=true; main.ChartConstantLine2.Active:=true; if main.FitlinButton.Caption='Fit linear' then begin main.FitlinButton.Caption:='Select interval'; main.LinFuncSeries.Active:=false; main.ExpFuncSeries.Active:=false; main.FitlinButton.Color:=clRed; main.ChartConstantLine1.Position:=0.1*main.Chart.AxisList[1].Range.Max; main.ChartConstantLine2.Position:=0.9*main.Chart.AxisList[1].Range.Max; linfitb:=false; expfitb:=false; end else begin main.FitlinButton.Caption:='Fit linear'; main.FitlinButton.Color:=clSilver; getinterval_dt; N:=n1-n0; for i:=1 to N do begin XX[i,1]:=data_list[n0+i-1].dt; XX[i,2]:=1; YY[i]:=data_list[n0+i-1].thermof; end; MulFit(XX, YY, 1, N, 2, false, B, V); a:=B[1]; zero:=B[2]; da:=sqrt(abs(V[1,1])); dzero:=sqrt(abs(V[2,2])); linfitb:=true; main.LinFuncSeries.Active:=true; end; end; procedure Tmain.FitexpButtonClick(Sender: TObject); var i,j:longint; N:longint; Maxiter:longint=10000; Tol:Float=1e-4; begin if datanum=0 then exit; if not peltierm then exit; clearlines; 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.FitexpButton.Color:=clRed; main.ChartConstantLine1.Position:=0.1*main.Chart.AxisList[1].Range.Max; main.ChartConstantLine2.Position:=0.9*main.Chart.AxisList[1].Range.Max; linfitb:=false; expfitb:=false; end else begin main.FitexpButton.Caption:='Fit exp.'; main.FitexpButton.Color:=clSilver; getinterval; N:=n1-n0; for i:=1 to N do begin XXn[i]:=data_list[i+n0].time; YY[i]:=data_list[i+n0].dT+50; end; SetParamBounds(1, -200, 200); SetParamBounds(2, -1, 1e12); SetParamBounds(3, -1000, 1000); B[3]:=data_list[datanum-1].dT+50; B[2]:=-(ln(YY[N]-B[3])-ln(YY[1]-B[3]))/(XXn[N]-XXn[1]); B[1]:=(YY[1]-B[3])/exp(-B[2]*XXn[1]); //writeln(B[1],' ',B[2],' ',B[3]); NLFit(RegFunc, DerivProc, XXn, YY, 1, N, MaxIter, Tol, B, 1, 3, V); //writeln(B[1],' ',B[2],' ',B[3]); B[3]:=B[3]-50; T_0:=B[1]; beta:=B[2];T_inf:=B[3]; dT_0:=sqrt(abs(V[1,1])); dbeta:=sqrt(abs(V[2,2]));dT_inf:=sqrt(abs(V[3,3])); expfitb:=true; main.ExpFuncSeries.Active:=true; end; end; procedure Tmain.ChartAfterDraw(ASender: TChart; ADrawer: IChartDrawer); var x0,y0,dy,x,y:longint; scale:longint=1; s:string; begin if (not linfitb) and (not expfitb) then exit; //if printscale then scale:=3; x0:=scale*100;y0:=scale*20; x:=x0;y:=y0; dy:=round(1.5*ADrawer.TextExtent('A',tfhtml).y); ADrawer.SetFont(Chart.Title.Font); if linfitb then begin x:=x0; y:=y+dy; s:='U(T)=a'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='&Delta'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; s:='T+b'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x+ADrawer.TextExtent(s,tfhtml).x; 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)+' mV/°C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; y:=y+dy; x:=x0; s:='b= '+floattostrf(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(dzero,ffGeneral,2,0)+' mV'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; end; if expfitb then begin x:=x0; s:='T(t)=A 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)+Tinf'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; x:=x0; y:=y+dy; 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:='A= '+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+dy; x:=x0; s:='Tinf= '+floattostrf(T_inf,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_inf,ffGeneral,2,0)+' °C'; ADrawer.TextOut.Pos(x,y).TextFormat(tfhtml).Text(s).Done; end; end; procedure loaddraw; var p:text; i:longint; dumi:double; var s:string; begin {$I-} ioresult; assign(p,Main.OpenDialog.FileName); reset(p); readln(p,s); peltierm:=false; if pos('I [A]',s)<>0 then peltierm:=true; i:=0; repeat inc(i); read(p,data_list[i].time); read(p,data_list[i].dT); read(p,data_list[i].T1); read(p,data_list[i].T2); if peltierm then readln(p,data_list[i].current) else readln(p,data_list[i].thermof); until eof(p); close(p); datanum:=i; timemax:=1.05*data_list[i-1].time; timemin:=0; main.Timeeditmax.value:=timemax; main.Timeeditmin.value:=0; main.Chart.AxisList[4].Range.Max:=main.Timeeditmax.value; main.Chart.AxisList[4].Range.Min:=main.Timeeditmin.value; tempmax:=1.05*data_list[i-1].dt; tempmin:=data_list[1].dt; if tempmax ChartToolsetDataPointDragTool then exit; end; procedure Tmain.CommandKeyPress(Sender: TObject; var Key: char); begin if byte(key)=13 then begin sendUSB(command.text); 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.