Title :CMCBEDON Keywords :CBED, Thickness, TEM Computer Control Computer :IBM PC Operating System :DOS Programming Language :Pascal Hardware Requirements :Philips CM Series Computer Interface Author(s) :M.T. Otten Correspondence Address :Philips Analytical :International Business Centre :Electron Optics,Building AAE :5600 MD Eindhoven,The Netherlands Abstract: CMCBEDON is an on-line computer program which allows the user of a Philips CM series TEM/STEM to determine specimen thicknesses using convergent beam electron diffraction patterns. Unlike CMCBEDOFF, this program requires a Philips CM series computer/microscope interfaces. Using interactive programing data required for calculations is supplyed/measured directly from microscope. No micrographs are therefore required. July 1989 -------------------------------------------------------------------------- Title :CMCBEDON Keywords :CBED, Thickness, TEM Computer Control Computer :IBM PC Operating System :DOS Programming Language :Pascal Hardware Requirements :Philips CM Series Computer Interface Author(s) :M.T. Otten Correspondence Address :Philips Analytical :International Business Centre :Electron Optics,Building AAE :5600 MD Eindhoven,The Netherlands -------------------------------------------------------------------------- Operating Instructions for On-Line and Off-Line CBED Thickness Measurements on the Philips CM Microscope M.T. Otten Philips Analytical International Business Centre -- Electron Optics Building AAE 5600 MD Eindhoven THE NETHERLANDS JULY 1989 Operating Instructions for On-Line CBED Thickness Measurement INTRODUCTION This manual describes the operation of program CBED for on-line and program CBEDOFF for off-line measurement of thickness through Convergent Beam Diffraction. In principle, the on-line measurement can be done by using the internal CM measurement in diffraction and converting the d spacings given by the microscope to real distances, but it is very difficult to shift perpendicularly from one fringe to the next, resulting in substantial measurement errors. Program CBED still uses the internal measurement of the CM microscope by Remote Control, but by using the cursor keys of the computer the shift is made automatically perpendicular to the fringes. The necessary data are collected and the thickness determined directly by the program. The instructions necessary for execution are shown on the screen of the Remote Control computer. NOTE: These programs are unsupported software. They may be distributed and/or modified freely. They may not be copyrighted by any individual other than the author or Philips Electron Optics. Philips Electron Optics is under no circumstances responsible for any errors in the software or any damage resulting from its use. Programs CBED and CBEDOFF run on IBM-compatible computers (IBM is a trademark of the International Business Machines Corporation (that obey the conditions specified for Remote Control of the CM microscope. Program CBED has been tested on an XT-compatible. It may not work on an AT-compatible because of the higher processing speed which can produce some problems in com- munication with the microscope. Print-out is formatted for an EPSON dot-matrix printer. The following files are supplied with the program: CBED.INS The text of these operating instructions (WordPerfect format) CBED.COM The program itself CBED.PAS Its source code RCM.INC Include files containing: Remote Control subroutines REMCBED.INC Remote Control subroutines CBEDOFF.COM A similar program for off-line measurements CBEDOFF.PAS Its source code LINEAR.PAS Linear Regression Include file INSTALLATION Installation of the program on a floppy disc or the hard disc is done by using the MS-DOS copy command. For two floppy-disc drive systems: Insert the program disc in drive b and the MS-DOS bootable disc in a: Type COPY B:CBED.COM A: and press the carriage return. Type COPY B:CBEDOFF.COM A: and press the carriage return. Remove the program disc and insert a data disc in drive b: NOTE: The active disc during running of the program may not be write- protected (silver sticker on the side) because the program must be able to write a log file on the disc. For one floppy-disc plus hard disc drive systems: Insert the program disc in drive a: Type COPY A:CBED.COM C: and press the carriage return. Type COPY A:CBEDOFF.COM C: and press the carriage return. Remove the program disc THEORETICAL BACKGROUND High accurate thickness measurements can be done by determining the spacings of the subsidiary fringes visible parallel to the Kikuchi line in Dark-Field discs. The method is outlined in: Kelly, P.M., Jostsons, A., Blake, R.G., and Napier, J.G. (1975), Phys. Stat. Sol. A31, 771. The data required for the measurement are: (1) the high tension (2) the d spacing of the Dark-Field disc used (3) a measurement of the distance between the Bright-Field and Dark- Field discs (4) the distances between the dark subsidiary fringes and the central Kikuchi line For measuring thickness through convergent beam diffraction the formula is used, where Si is the deviation parameter, l the electron wavelength, dhkl the d-spacing of the diffraction used, ni are the distances from the central bright fringe to the dark fringes 1, 2, etc. and 2 qB the distance in the pattern representing the Bragg angle. When (Si/ni)2 is plotted against (1/ni)2, where ni is the number of the dark fringe (1,2,3, etc.), the plot yields a straight line, if ni was chosen correctly. If ni was incorrect (at larger thickness fringes, 1,2,3 gradually disappear so the first dark fringe becomes 2,3,4 etc.), then the plot yields a curved line. The thickness of the specimen is derived from the intercept, which is equal to (1/t)2. The slope of the line is equal to -(1/ )2, where is the extinction distance of the operating diffraction. Because the thickness measurement depends mostly on the higher-order fringes, it is highly accurate and rather insensitive to measuring errors or to the assignment of ni. The slope, however, depends very much on the measurement of the first fringe and is, therefore, much more susceptible to analytical error. In the program the assignment of ni, is done on the basis of the correlation coefficient, which should be -1.0 for a perfect fit to the straight line. A number of assignments are tested and the one with the lower correlation coefficient taken to be the correct one. If the line gives a positive slope, the results are rejected as a bad measurement. RUNNING PROGRAM CBED WARNING: In order to perform the on-line measurement, the following condi- tion must be set on the PRINTING PARAMETERS page of the MICROCONTROLLER: except for OPERATION, all selections of GENERAL DATA, SCANNING DATA (if present) and SERVICE DATA must be off. This is necessary, because the program retrieves the high tension and the d spacing through a log file. If selections other than OPERATION are on, logging takes too long and the program will interrupt data logging, which causes the microscope to be no longer Remote Controllable. In order to make Remote Control again possible when that happens, the micro- scope must be restarted (small RESTART button underneath DATA DIM). At all times the program can be stopped by pressing Ctrl-C (press the Ctrl key and the C at the same time). However, it is advisable to observe the light of the disc drive used for logging to see if any action is taken there. If the light is out, the program can be stopped without any problems. The measurement of the d spacing forms an important part of the measure- ment. The internal diffraction measurement of the CM microscope must there- fore have been calibrated (in view of the stability, this calibration needs to be done only once every couple of months or so) and the specimen must be in the eucentric position. In order to perform a thickness measurement, the operator must first obtain a Convergent Beam Pattern that shows the thickness fringes. It is important that the condition be as near as possible to a two-beam condition (the dark Kikuchi line goes through the middle of the Bright- Field disc). In general, the conditions necessary to have a sufficiently large disc spacing are obtained in nanoprobe mode. Focus the beam on the specimen and press the Diffraction button. If necessary, switch to a larger or smaller C2 aperture (which will affect the size of the discs). Select a camera length (the higher the camera length the more accurate the measurement) such that the Bright-Field disc and the Dark-Field disc are both still visible on the screen. Start the program by typing CBED and a carriage return, while the computer is in MS-DOS. The program will now determine several things, such as the position of the PRINTING PARAMETERS (2 on a TEM, 4 on a STEM) and will switch OPERATION and MEASURING on the PRINTING PARAMETERS page if necessary. As long as the introductory messages are present on the screen, it is not essential that the microscope is already in diffraction with a focussed beam, so if beam damage or contamination is problematic, focusing of the beam can be done afterwards. Do not interfere with the program by touching any knobs on the microscope. Once the necessary data have been collected, a schematic of the Convergent Beam Pattern is shown on the screen. If not already done, focus the beam and go to Diffraction. Since the determination of the centre of the diffraction discs is rather difficult to do with a high degree of accuracy, the program determines the centres from: (1) the intersection of the dark Kikuchi line and the rim of the Bright- Field disc (it doesnÕt matter on which side); (2) the intersection of the bright Kikuchi line and the rim of the Dark- Field disc (on the same side as the previous measurement); (3) the other intersection of the bright Kikuchi line with the rim of the Dark-Field disc. When so instructed by the program, the operator should move these three points to a reference point such as the tip of the beam stop. For good accuracy it is more important that the Kikuchi lines are positioned precisely on the reference point that it is exactly at the rim of the disc. For moving the pattern, the operator must use the cursor keys of the computer. Using the SHIFT knobs directly will interfere with the measurement and produce poor results. The cursor keys are organized as follows: The arrow keys produce a slow shift in the four perpendicular directions. It is possible that the absolute shift direction does not coincide with that of the screen due to the rotation of the diffraction pattern. The Home, End, Page Down, and Up keys produce a rapid shift in the same four directions. The direction of these keys is such that the shift they produce corresponds to the arrow key 1/8 turn anti-clockwise so that: Home = 10 x arrow right Page Up = 10 x arrow up Page Down = 10 x arrow left End = 10 x arrow down (NOTE: The deviation from their normal usage was found to be more logical in operation at the microscope.) Each point is entered by hitting the carriage return. Once the three points have been determined, the program shifts the diffraction pattern so that the reference point is in the centre of the Dark-Field disc. The operator then shifts the fringes one by one to the reference point with the cursor keys. Again the Home, End, Page Up, and Page Down produce the coarser shift. All shifts are now per- pendicular to the fringes, whether horizontal or vertical cursors are used. The position of the fringes are again entered by hitting the carriage return. Once enough fringes have been measured (four or five should, in general, be enough), hit the carriage return again without further shifting and the program will do the fit to the straight line and produce the measurement results. For the measurement it is not important whether the first fringes are included or not, but all fringes measured should be in a complete sequence; e.g., the sequence 2,3,4,5 is allowed but not 1,3,4,6. Once results are obtained, the progrm asks if they should be printed. If yes, the operator can add text to the print-out, which will contain the high tension, electron wavelength, d spacing, fringe measurements, line fit data, thickness, and the extinction distance. After that the program asks if more measurements are to be performed. If not, the program returns control to MS-DOS. RUNNING PROGRAM CBEDOFF Program CBEDOFF is started by typing CBEDOFF and hitting a carriage return while the computer is in MS-DOS. At all times the program can be stopped by pressing Ctrl-C (press the Ctrl key and the C at the same time). In order to perform a thickness measurement, the operator must first have a Convergent Beam Pattern that shows the thickness fringes. It is important that the condition be as near as possible to a two-beam condition (the dark Kikuchi line goes through the middle of the Bright- Field disc). In general, the conditions necessary to have a sufficiently large disc spacing are obtained in nanoprobe mode. The data required for the measurement are: (1) the high tension (in kV) (2) the d spacing of the Dark-Field disc used (in nm) (3) a measurement of the distance between the Bright-Field with Dark- Field discs (in arbitrary units, but the same as of item 4) (4) the distance between the dark subsidiary fringes and the central Kikuchi line (in the same units as item 3) Start the program by typing CBEDOFF followed by a carriage return. The program will display messages explaining the input data required. If those data have been collected, typing Y will continue into the program, N will return to MS-DOS. The program will then ask for the input data. For the measurement it is not important whether the first fringes are included or not, but all fringes measured should be in a complete sequence; e.g., the sequence, 2,3,4,5 is allowed but not 1,3,4,6. Once results are obtained, the program asks if they should be printed. If yes, the operator can add text to the printout, which will contain the high tension, electron wavelength, d spacing, fringe measurements, line fit data, thickness, and the extinction distance. After that the program asks if more measurements are to be performed. If not, the program returns control to MS-DOS. Title :CMCBEDON Keywords :CBED, Thickness, TEM Computer Control Computer :IBM PC Operating System :DOS Programming Language :Pascal Hardware Requirements :Philips CM Series Computer Interface Author(s) :M.T. Otten Correspondence Address :Philips Analytical :International Business Centre :Electron Optics,Building AAE :5600 MD Eindhoven,The Netherlands -------------------------------------------------------------------------- program CBED_On_Line; {######################################################################### Program to perform on-line CBED thickness measurement Written by Max T. Otten Philips Analytical, Electron Optics Applications Laboratory, Building AAE, 5600 MD Eindhoven, The Netherlands Copyright Philips Analytical, Electron Optics This program may be distributed freely. It may not be sold for for profit in its original or any modified version. #########################################################################} {$r+} { index range check } { ********************** General declarations **************************** } var Query,Esc : Char; Index2,Vd,X_Screen,Y_Screen : Integer; label TestCM,Double,Quit; { ********************** Remote Control declarations ********************* } const Ready = 07; { pushbutton constant } Shiftx = 12; { turn knob constant } Shifty = 13; var Soft_id,Soft_count,Press,Page,X,Y,X_dif,Y_dif : Integer; Stop : Boolean; X_pos,Y_pos,X_Incr,Y_Incr : Real; Origin,XY_BF,XY_DF,XY_DF_Mid : Array[1..2] of Real; {---------------------------------------------------------------------------} { ********************** CBED declarations ******************************* } var Index,Fringe_Index,Fringe_Temp : Integer; Slope,Intercept,Corr_Coeff,Old_Coeff : Real; Volt,Lambda,d_spacing,Disc_Spacing : Real; Fringe_test : Boolean; Measured : Array[1..30] of Real; Annotation : String[80]; Info_String : String[3]; label FrTest,FrLoop,Results,Fringe_Repeat; type Number = 1..30; Arr = Array[Number] of Real; Txt = String[3]; var Ni,Dev_Param : Arr; Fringe : Number; {---------------------------------------------------------------------------} procedure Beep; { sounds a beep } begin sound(500); delay(500); nosound; end; {---------------------------------------------------------------------------} procedure NoDriver; { writes a message on the screen if there is no driver } begin ClrScr; Writeln; Writeln('ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿'); Writeln('³ ³'); Writeln('³ The device driver is not present. ³'); Writeln('³ In the root directory of the disk you boot from is the file CONFIG.SYS. ³'); Writeln('³ This normal ASCII file must contain the following phrase: ³'); Writeln('³ ³'); Writeln('³ Device = RCM.SYS ³'); Writeln('³ ³'); Writeln('³ If you do not wish to place the file RCM.SYS in the root directory, but ³'); Writeln('³ for example in the directory C:\RemoteCM, then this phrase must be: ³'); Writeln('³ ³'); Writeln('³ Device = C:\RemoteCM\RCM.SYS ³'); Writeln('³ ³'); Writeln('³ You can change the file config.sys with any normal ASCII text editor. ³'); Writeln('³ Please correct this, then boot again. ³'); Writeln('³ ³'); Writeln('ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ'); Writeln; end; { of procedure NoDriver } {---------------------------------------------------------------------------} {$iRCM.INC} { the functions open/close and write to the device driver } {$iREMCBED.INC} { extended control functions } {---------------------------------------------------------------------------} procedure Press_READY; {presses the READY pushbutton } begin Press := 2; if not Pushbutton(Ready,Press) then begin beep; beep; WriteLn('Error in pressing READY pushbutton'); end; end; {---------------------------------------------------------------------------} procedure Press_Softkey(Soft_id,Soft_count: Integer); { presses softkey Soft_id } begin if not Softkey(Soft_id,Soft_count) then begin beep; beep; WriteLn('Error in pressing softkey'); end; end; {---------------------------------------------------------------------------} procedure Shift_XY(var X,Y: Integer); { turns Shift X and/or Y knobs X and Y times } begin if X <> 0 then if not Turnknob(Shiftx,X) then begin beep; beep; WriteLn('Error in shift X'); end; if Y <> 0 then if not Turnknob(Shifty,Y) then begin beep; beep; WriteLn('Error in shift Y'); end; end; {---------------------------------------------------------------------------} procedure Start_Log; { starts data logging in file NONAME.DAT } var Filename : String[10]; Append : boolean; begin Filename := 'NONAME.DAT'; Append := false; if not StartDisplInfo(Filename,Append) then begin beep; beep; WriteLn('Error in starting log file'); end; end; {--------------------------------------------------------------------------} procedure Stop_Log; { stops data logging } begin Delay(3000); if not StopDisplInfo then begin beep; beep; WriteLn('Error in stopping log file'); end; end; { of procedure Stop_Log } {---------------------------------------------------------------------------} procedure Retrieve(var Info : real; In_String : Txt); { gets voltage and d-spacing } label Found; var Result,Position,Loop_index,Index : Integer; Test_string : string[80]; Result_string : string[6]; OK : Boolean; IO_File : Text; begin Result_string := ''; { make string empty } Assign(IO_File,'NONAME.DAT'); OK := (IOResult = 0); if OK then begin {$I-} Reset(IO_File); {$I+} OK := (IOResult=0); end; Index := 0; if OK then begin while not EOF(IO_File) do begin ReadLn(IO_File,Test_string); Position := pos(In_String,Test_string); if Position > 0 then begin if (In_String = 'ht:') then goto Found else if (In_string = 'd1:') then Index := Index + 1; if Index = 2 then goto Found; end; if EOF(IO_File) then WriteLn('Error in finding ',In_String); end; end; Found: { string has been found, now get numbers } Index := 0; for Loop_index := 3 to 10 do begin if Test_string[Position + Loop_index] in ['0'..'9'] then begin Index := Index + 1; Result_String[Index] := Test_string[Position + Loop_index]; end; if Test_string[Position + Loop_index] = Chr(46) then begin Index := Index + 1; Result_String[Index] := Test_string[Position + Loop_index]; end; end; Result_String[0] := Chr(Index); { watch out, if this isn't done the val function screws up } val(Result_String,Info,Result); if Result >0 then WriteLn('Error in string to real conversion'); if (In_String = 'd1:') and (Info > 10) then Info := Info / 1000; { if so it means pm instead of nm } OK := OK and (IOResult = 0); if OK then Close(IO_File); end; {---------------------------------------------------------------------------} function Empty_File : Boolean; { Clears old NONAME.DAT file } var OK : Boolean; IO_File : Text; begin Empty_File := false; Assign(IO_File,'NONAME.DAT'); OK := (IOResult = 0); if OK then begin {$I-} Reset(IO_File); {$I+} OK := (IOResult=0); end; if OK then Rewrite(IO_File); OK := OK and (IOResult = 0); if OK then begin Empty_File := true; Close(IO_File); end; end; {---------------------------------------------------------------------------} function Test_HT : Boolean; { tests if the string ht: occurs in log } label HT_test; var Result : Integer; Test_string : string[80]; OK : Boolean; HT_pos : Integer; IO_File : Text; begin Test_HT := false; Assign(IO_File,'NONAME.DAT'); OK := (IOResult = 0); if OK then begin {$I-} Reset(IO_File); {$I+} OK := (IOResult=0); end; if OK then begin while not EOF(IO_File) do begin readLN(IO_File,Test_string); HT_pos := pos('ht:',Test_string); if HT_pos > 0 then Test_HT := true; end; end; OK := OK and (IOResult = 0); if OK then Close(IO_File); end; {---------------------------------------------------------------------------} function Test_Meas : Boolean; { tests if the string MEASURE occurs in the log } label Meas_test; var Result : Integer; Test_string : string[80]; OK : Boolean; Meas_pos : Integer; IO_File : Text; begin Test_Meas := false; Assign(IO_File,'NONAME.DAT'); OK := (IOResult = 0); if OK then begin {$I-} Reset(IO_File); {$I+} OK := (IOResult=0); end; if Ok then begin while not EOF(IO_File) do begin readLN(IO_File,Test_string); Meas_pos := pos('MEASURE',Test_string); if Meas_pos > 0 then Test_Meas := true; end; end; OK := OK and (IOResult = 0); if OK then Close(IO_File); end; {---------------------------------------------------------------------------} procedure Invert_Video(var Vd : Integer); begin case Vd of 0 : begin Textcolor(Black); Textbackground(White); end; 1 : begin Textcolor(White); Textbackground(Black); end; end; Vd := Vd + 1; if Vd > 1 then Vd := Vd - 2; end; {---------------------------------------------------------------------------} procedure Function_Key(var FK : Integer); { gets cursor input } var Ch : Char; Previous : Boolean; Vd : Integer; label Return; begin Vd := 0; repeat if Y_Screen = 2 then begin GotoXY(X_Screen,1); Write('|'); GotoXY(X_Screen,2); Write('V'); Invert_Video(Vd); Delay(250); end else begin GotoXY(X_Screen,14); Write('^'); GotoXY(X_screen,15); Write('|'); Invert_Video(Vd); Delay(250); end; until keypressed; Read(Kbd,Ch); { Read a character from the keyboard } if (Ch=chr(13)) then begin FK := Ord(Ch); goto Return; end; if (Ch=chr(27)) and keypressed then begin { Character must be either ESC key or } Previous:=True; { one that generates a two-digit code } Read(Kbd,Ch); { Read the character following ESC } end else Previous:=False; if Previous then FK := Ord(Ch) else FK := 0; Return: end; {---------------------------------------------------------------------------} procedure Cursor_Shift(var X_pos,Y_pos: Real); { turns shift knobs through cursor } var Cursor : Integer; begin repeat X := 0; Y := 0; Function_Key(Cursor); case Cursor of 80 : Y := 10; {down} 72 : Y := -10; {up} 75 : X := -10; {left} 77 : X := 10; {right} 79 : Y := 100; {End} 73 : Y := -100; {PgUp} 71 : X := -100; {Home} 81 : X := 100; {PgDn} end; X_pos := X_pos + X; Y_pos := Y_pos + Y; Shift_XY(X,Y); until Cursor = 13; end; {----------------------------------------------------------------------------} procedure Shift_Perp(var X_pos,Y_pos: Real); { shifts perpendicularly } var Cursor : Integer; Factor : Integer; begin repeat Factor := 0; Function_Key(Cursor); case Cursor of 77,80 : Factor := 3; 72,75 : Factor := -3; 71,73 : Factor := -25; 79,81 : Factor := 25; end; X_pos := X_pos + X_Incr * Factor; Y_pos := Y_pos + Y_Incr * Factor; X := Trunc( X_pos - XY_DF_Mid[1] ) - X_dif; if X <> 0 then X_dif := X_dif + X; Y := Trunc( Y_pos - XY_DF_Mid[2] ) - Y_dif; if Y <> 0 then Y_dif := Y_dif + Y; Shift_XY(X,Y); until Cursor = 13; end; {----------------------------------------------------------------------------} procedure Linear_Regression(var Xpar : Arr ; var Ypar : Arr ; var N_XY : Number; var Slope,Intercept,Corr_Coeff: Real); { Procedure calculates a linear regression, where Xpar and Ypar are input data arrays of N elements. Xpar is assumed to be the errorless value. Returned values are Slope, Intercept and Corr_Coeff. } var Sum_X,Sum_Y : Real; Sum_Cross_Product,Sum_Squares_X,Sum_Squares_Y : Real; index : Integer; begin Sum_X := 0 ; Sum_Y := 0 ; Sum_Cross_Product := 0 ; Sum_Squares_X := 0 ; Sum_Squares_Y := 0 ; Index := 0 ; repeat index := index + 1; Sum_X := Sum_X + Xpar[index]; Sum_Y := Sum_Y + Ypar[index]; Sum_Cross_Product := Sum_Cross_Product + Xpar[index] * Ypar[index]; Sum_Squares_X := Sum_Squares_X + sqr(Xpar[index]); Sum_Squares_Y := Sum_Squares_Y + sqr(Ypar[index]); until index = N_XY; Slope := ( Sum_Cross_Product - Sum_X * Sum_Y / N_XY ) / ( Sum_Squares_X - sqr(Sum_X) / N_XY ) ; Intercept := Sum_Y / N_XY - Slope * Sum_X / N_XY ; Corr_Coeff := ( Sum_Cross_Product - Sum_X * Sum_Y / N_XY ) / sqrt( ( Sum_Squares_X - sqr(Sum_X) / N_XY ) * ( Sum_Squares_Y - sqr(Sum_Y) / N_XY )) ; end; {##########################################################################} begin { main program } Esc := Chr(27); { used for printing } { Introductory messages } NormVideo; ClrScr; GotoXY(9,1); Write('CBED thickness measurement program for CM microscopes'); GotoXY(22,3); Write('version 2.1 July 1989'); GotoXY(27,5); Write('by Max T. Otten'); GotoXY(13,7); Write('Philips Electron Optics - Applications Laboratory'); GotoXY(13,8); Write('Building AAE, 5600 MD Eindhoven, The Netherlands'); GotoXY(1,10); Write('--------------------------------------------------------------------------------'); LowVideo; { Check if Remote Control driver can be opened, if not stop } GotoXY(1,12); Write('Testing presence of RC driver .... '); Stop := not OpenRemoteCM; if Stop then begin NoDriver; goto Quit; end; { Check if microscope is Remote Controllable } TestCM: GotoXY(1,12); ClrEol; GotoXY(1,13); ClrEol; GotoXY(1,14); ClrEol; GotoXY(1,12); Write('Testing if equipment available ....'); if not EquipmentAvailable then begin beep; beep; GotoXY(1,12); WriteLn('Microscope is not Remote Controllable,'); WriteLn('please check if Remote Control function is switched on.'); Write('Do you wish to continue ? (Y/N) '); Read(Query); if UpCase(Query) = 'N' then goto Quit else goto TestCM; end; { Empty any existing NONAME.DAT file } If not Empty_File then begin GotoXY(1,12); Write('Cannot empty NONAME.DAT file'); Delay(2000); end; { Find out where the print parameters page is (2 on TEM, 4 on STEM) } GotoXY(1,12); Write('Searching for print parameters page ....'); Press_READY; Start_Log; Press_Softkey(9,2); Press_Softkey(8,1); { If on print page -> output } Delay(5000); Stop_Log; { long delays necessary because of slow logging } if Test_HT then { ht found } Page := 2 else begin Start_Log; Press_Softkey(2,3); Press_Softkey(3,1); Press_Softkey(8,1); Delay(5000); Stop_Log; if Test_HT then { output found after switching on OPERATION } Page := 2 else begin { First reset softkeys on STEM parameters page } Press_Softkey(0,2); Press_Softkey(10,2); Press_Softkey(11,3); { then get ready for printing } Press_READY; Start_Log; Press_Softkey(9,4); Press_Softkey(8,1); { Print output on STEM } Delay(5000); Stop_Log; if Test_HT then {output found on page 4 } Page := 4 else begin Start_Log; Press_Softkey(2,3); Press_Softkey(3,1); Press_Softkey(8,1); Delay(5000); Stop_Log; if Test_HT then Page := 4 else begin beep; beep; beep; WriteLn; WriteLn('Error in finding printing page') end; end; end; end; GotoXY(1,13); Write('Print parameters page = ',page,' '); { Switch measure on and test } GotoXY(1,12); Write('Switching measurement printing on .... '); Press_READY; Start_Log; Press_Softkey(13,1); Press_Softkey(15,1); Stop_Log; Press_READY; if not Test_Meas then begin Start_Log; Press_Softkey(9,Page); Press_Softkey(1,1); Press_READY; Press_Softkey(13,1); Press_Softkey(15,1); Stop_Log; if not Test_Meas then WriteLn('Error in switching on printing of measurements') end; Double: { return point for more measurements } Volt:=0; Lambda:=0; Index:=0; Fringe_Index:=0; Slope:=0; Intercept:=0; Corr_Coeff:=0; Old_Coeff:=0; d_spacing:=0; Disc_Spacing:=0; X_pos := 0; Y_pos := 0; { Do a direct print to get the high tension later } GotoXY(1,13); ClrEol; Press_READY; GotoXY(1,12); Write('Getting high tension .... '); Start_Log; Press_Softkey(9,Page); Press_Softkey(8,1); Delay(2000); { Fill aray with zero's } for Index := 1 to 30 do Measured[Index] := 0; { Shift to the intersection of the Bright-Field disc and the Kikuchi line, press ENTER } ClrScr; Press_READY; Press_Softkey(13,1); LowVideo; GotoXY(1,3); WriteLn; WriteLn(' ÜßßßßÛßßßßÜ ÜßßßßÛßßßßÜ '); WriteLn(' Üß Û ßÜ Üß Ý Û Þ ßÜ '); WriteLn(' Üß Û ßÜ Üß Ý Ý Û Þ Þ ßÜ '); WriteLn(' Üß Û ßÜ Üß Ý Ý Ý Û Þ Þ Þ ßÜ'); WriteLn(' Û Û Û Û Ý Ý Ý Ý Û Þ Þ Þ Þ Û'); WriteLn(' ßÜ Û Üß ßÜ Ý Ý Ý Û Þ Þ Þ Üß'); WriteLn(' ßÜ Û Üß ßÜ Ý Ý Û Þ Þ Üß'); WriteLn(' ßÜ Û Üß ßÜ Ý Û Þ Üß'); WriteLn(' ßÜÜÜÜÛÜÜÜÜß ßÜÜÜÜÛÜÜÜÜß'); WriteLn; WriteLn; WriteLn; WriteLn(' BRIGHT FIELD DARK FIELD'); GotoXY(1,18); WriteLn('Shift intersection between rim of Bright-Field disc and Kikuchi line'); Write('to the reference point '); NormVideo; Write('using the cursors '); LowVideo; WriteLn('on the computer.'); WriteLn('Press ENTER when finished'); WriteLn; WriteLn('Normal cursors give low speed, Home / End / PgUp / PgDn give high speed'); Vd := 0; X_Screen := 20; Y_Screen := 2; Cursor_Shift(X_pos,Y_pos); Vd := 1; Invert_Video(Vd); XY_BF[1] := X_pos; XY_BF[2] := Y_pos; Press_Softkey(15,1); { Shift to intersection between Dark Field disc and Kikuchi line } GotoXY(1,1); ClrEol; GotoXY(1,2); ClrEol; GotoXY(1,18); ClrEol; LowVideo; GotoXY(1,18); Write('Shift intersection between rim of Dark-Field disc and Kikuchi line'); X_Screen := 60; Cursor_Shift(X_pos,Y_pos); Vd := 1; Invert_Video(Vd); Press_Softkey(15,1); XY_DF[1] := X_pos; XY_DF[2] := Y_pos; Disc_Spacing := Sqrt ( sqr( XY_BF[1]-XY_DF[1] ) + sqr( XY_BF[2]-XY_DF[2] ) ); { Retrieve measurement from log file } for Index2 := 18 to 24 do begin GotoXY(1,Index2); ClrEol; end; GotoXY(1,20); Write('Please wait ....'); Stop_Log; Delay(3000); Info_String := 'ht:'; Retrieve(Volt,Info_String); Lambda := 0.0388/(sqrt(Volt)*sqrt(1+0.000978*Volt)); Info_String := 'd1:'; Retrieve(d_spacing,Info_String); { Shift to other intersection of Dark-Field disc and Kikuchi line } GotoXY(1,1); ClrEol; GotoXY(1,2); ClrEol; LowVideo; GotoXY(1,18); GotoXY(1,18); WriteLn('Shift second intersection between rim of Dark-Field disc and Kikuchi line'); Write('to the reference point '); NormVideo; Write('using the cursors '); LowVideo; WriteLn('on the computer.'); WriteLn('Press ENTER when finished'); WriteLn; WriteLn('Normal cursors give low speed, Home / End / PgUp / PgDn give high speed'); X_Screen := 60; Y_Screen := 15; Cursor_Shift(X_pos,Y_pos); Vd := 1; Invert_Video(Vd); { Determine mid position and shift there } XY_DF_Mid[1] := ( XY_DF[1] + X_pos ) / 2; XY_DF_Mid[2] := ( XY_DF[2] + Y_pos ) / 2; X := Trunc(XY_DF_Mid[1] - X_pos) ; Y := Trunc(XY_DF_Mid[2] - Y_pos); Shift_XY(X,Y); X_pos := XY_DF_Mid[1]; Y_pos := XY_DF_Mid[2]; { Now determine how to shift perpendicularly } Origin[1] := XY_DF_Mid[1] - XY_DF[1] + XY_BF[1]; Origin[2] := XY_DF_Mid[2] - XY_DF[2] + XY_BF[2]; X_Incr := ( XY_DF_Mid[1] - Origin[1] ) / sqrt( sqr( XY_DF_Mid[1] - Origin[1]) + sqr(XY_DF_MID[2]) - Origin[2] ); Y_Incr := ( XY_DF_Mid[2] - Origin[2] ) / sqrt( sqr( XY_DF_Mid[1] - Origin[1] ) + sqr( XY_DF_MID[2]) - Origin[2] ); X_dif := 0; Y_dif := 0; { Start measuring the fringes } Fringe_Temp := 0; for Index2 := 18 to 24 do begin GotoXY(1,Index2); ClrEol; end; LowVideo; GotoXY(1,19); NormVideo; Write('using the cursors '); LowVideo; WriteLn('on the computer.'); WriteLn; WriteLn('Shift is automatically perpendicular to the fringes'); WriteLn; WriteLn('Normal cursors give low speed, Home / End / PgUp / PgDn give high speed'); X_Screen := X_Screen - 1 ; repeat Fringe_Repeat: Fringe_Temp := Fringe_Temp + 1; GotoXY(1,14); ClrEol; GotoXY(1,15); ClrEol; GotoXY(1,18); ClrEol; GotoXY(1,18); LowVideo; Write('Shift dark fringe number ',Fringe_Temp:3,' to the reference point '); X_Screen := X_Screen - 2; Shift_Perp(X_pos,Y_pos); Vd := 1; Invert_Video(Vd); Measured[Fringe_Temp] := sqrt( sqr( X_pos - XY_DF_Mid[1] ) + sqr( Y_pos - XY_DF_Mid[2] ) ); if Fringe_Temp = 1 then goto Fringe_repeat; until Abs( Measured[Fringe_Temp] - Measured[Fringe_Temp-1]) < 0.5; Fringe := Fringe_Temp-1; { Process data using formula (Si/Ni)**2 where Si = lambda * meas. fringe spacing / sqr (d-spacing) * measured disc spacing } Old_Coeff := 0; Fringe_test := false; Fringe_Index := 0 ; FrLoop: Fringe_Index := Fringe_Index + 1; if Fringe_Index > 25 then begin Slope := 100; goto Results; end; FrTest: for Index := 1 to Fringe do begin Dev_Param[Index] := sqr( ( Lambda * Measured[Index] ) / ( sqr(d_spacing) * Disc_Spacing * (Index+Fringe_Index-1))); Ni[Index] := sqr(1/(Index+Fringe_index-1)) ; end; Linear_Regression(Ni,Dev_Param,Fringe,Slope,Intercept,Corr_Coeff); if Fringe_Test = false then if Fringe_Index = 1 then begin Old_Coeff := Corr_Coeff; goto FrLoop; end; if Fringe_Test = true then goto Results; if Old_Coeff < Corr_Coeff then begin Fringe_Index := Fringe_Index-1; Fringe_Test := true; goto FrTest; end; Old_Coeff := Corr_Coeff; goto FrLoop; Results: { is where program jumps after correct finge index was found } if Slope > 0 then { positive slope will screw up extinction distance } begin for Index2 := 18 to 24 do begin GotoXY(1,Index2); ClrEol; end; ClrScr; GotoXY(1,12); Write('Data do not converge, please measure again.'); GotoXY(1,13); Write('Press any key to continue'); Read(Query); goto Double; end; ClrScr; GotoXY(1,5); WriteLn('Accelerating voltage ',Volt:6:0,' kV ', 'Electron wavelength ',Lambda:8:5,' nm'); WriteLn('Diffraction d-spacing ',d_spacing:8:5,' nm'); WriteLn('Slope ',Slope: 12:8,' Intercept ',Intercept: 12:8); WriteLn('Corr. coefficient ',Corr_Coeff: 12:4); WriteLn; WriteLn('Fringe index starts with ',Fringe_Index); WriteLn('Specimen thickness is ',1/sqrt(Intercept):8:0,' nm'); WriteLn('Extinction distance is ',1/sqrt(-Slope):8:0,' nm'); { Ask if results must be printed } Query := ' '; WriteLn; Write('Print results ? (Y/N) '); Read(Query); if UpCase(Query) <> 'N' then begin WriteLn; WriteLn; WriteLn('Enter comments (maximum 60 characters) '); Read(Annotation); WriteLn(LST,Esc,'G'); WriteLn(LST); WriteLn(LST,Esc,'E','Convergent Beam Pattern Thickness Determination', Esc,'F'); WriteLn(LST,Annotation); WriteLn(LST); WriteLn(LST,'Accelerating voltage ',Volt:6:0,' kV ', 'Electron wavelength ',Lambda:8:5,' nm'); WriteLn(LST,'Diffraction d-spacing ',d_spacing:8:5,' nm'); WriteLn(LST,'Measured distance between central and diffracted disc', Disc_Spacing:6:2,' mm'); WriteLn(LST); WriteLn(LST,'Fringe no. Index Measured distance','(s', Esc,'S1','i',Esc,'T','/n',Esc,'S1','i',Esc,'T',')', Esc,'S0','2 ',Esc,'T'); for Index := 1 to Fringe do WriteLn(LST,' ',Index:3,' ', (Fringe_Index+Index-1):3,' ', Measured[Index]:6:2,' mm',Dev_Param[Index]:10:7); WriteLn(LST); WriteLn(LST,'Linear regression slope ',Slope:12:8,' and intercept', Intercept:12:8); WriteLn(LST,'Correlation coefficient ',Corr_Coeff:8:5); WriteLn(LST); WriteLn(LST,'Specimen thickness ',1/sqrt(Intercept):8:0,' nm'); WriteLn(LST,'Extinction distance ',1/sqrt(-Slope):8:0,' nm'); WriteLn(LST); WriteLn(LST); end; { Ask if another set of data must be processed } Query:= ' '; NormVideo; ClrScr; GotoXY(1,10); Write('Do another measurement ? (Y/N) '); LowVideo; Read(Query); if UpCase(Query) <> 'N' then goto Double; Quit: WriteLn; WriteLn; WriteLn('Program stopped'); end.