{CONTROL MACROS FOR THE ASI MFC-1 Microscope Focus Controller v1.0 2/5/95} { ASI, Inc. (503)485-2284 (voice) 3770 W 1st Ave. (503)687-2858 (fax) Eugene, OR 97402 info_asi@rain.com (email) } { This set of macros lets NIH-Image control the MFC-1 to drive and readout the microscope focus position. The drive uses a closed-loop DC servo rather than an open-loop stepper motor. Position information is from an encoder on the focus shaft. Drives supported as of 2/6/95 are: Zeiss Universal, UEM, and all Axio series Nikon Optiphot and Diaphot 200 & 300 Leitz LaborLux Olympus BH-2 Drive for Zeiss UEM controls both the head and stage. Drives for Zeiss Axio series perfectly compensate for the inherent slippage in the fine focus ball race mechanism used in these microscopes. The MFC-1 responds to the following ASCII commands: A [A]nnunciate command. MFC responds with an ASCII U or u to indicate "on line" and which of the two possible model numbers. G [G]o command. Moves a distance from current position. The distance moved is previously stored with the [I]ncremental amount command. I n1.....n6 [I]ncrement amount command. Parameters 1 to 6 are ASCII numbers representing amount to move from current position in tenths of microns. If the increment increases the distance between the slide and objective, preceed the number(s) by an ASCII - (minus sign). No sign implies positive values which move the slide and objective closer. Entering I200 will store 20.0 microns. Entering I-50 will store -5.0 microns. This command can be considered a relative move command. The I and G commands can be combined into one command for immediate increments, ie I200G moves the slide and objective closer together by 20.0 microns. M n1....n6 [M]ove command. Parameters 1 to 6 are ASCII numbers representing the amount to move (immediately) from the Zero position. If the movement increases the distance between the slide and objective, preceed the number(s) by an ASCII - (minus sign). No sign implies positive values which moves the slide and objective closer together. Entering M200 will move to postion 20.0 microns. Entering M-105 will move to position -10.5 microns. This command can be considered an absolute move command. R [R]ead position command. Reads back current position as n1....n6 or 1 to 6 ASCII numbers representing the distance from the zero position. A minus sign preceeding the numbers mplies that the slide is further away from the objective than the zero position. No sign (plus) implies they are closer. Z [Z]ero command. Sets the position (whereever it is) to Zero. Also cancels any M, I, or G command. Commands are bracketed by a Prefix and Suffix character, ASCII ^F and ^G respectively so multiple serial devices can be daisy chained on the Macintosh Modem port. } {----------------------------------------------------------------------} VAR {Global Variables} Prefix,Cmd1,CMD2,Suffix:integer MACRO 'Read ID'; var character,response:string; TimeOutTicks,ModelNumber: integer; TimeOut:boolean; begin Prefix:=06; Suffix:=07; Cmd1:=65; RequiresVersion(1.50); OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),Chr(Suffix))); response:=''; TimeOutTicks:=TickCount+2; repeat character:=GetSerial; response:=Concat(response,character); TimeOut:=TickCount>timeOutTicks; until (TimeOut); if response='' then PutMessage ('No MFC Detected'); ModelNumber:=ord(response); PutMessage('MFC Model:= ',ModelNumber, 'Note that Model 117 uses termination characters, Model 85 does not.'); end; {Read ID} MACRO 'Set Current Position Equal to Zero'; begin Prefix:=06; Suffix:=07; Cmd1:=90; { [Z]ero Postion Command } RequiresVersion(1.50); OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),Chr(Suffix))); end; {Set Current Position Equal to Zero} MACRO 'Read Position'; var TimeOutTicks:integer; position:real; character,response:string; TimeOut:boolean; begin Prefix:=06; Suffix:=07; Cmd1:=82; { [R]eport Position Command} RequiresVersion(1.50); OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),Chr(Suffix))); response:=''; TimeOutTicks:=TickCount+2; repeat character:=GetSerial; response:=Concat(response,character); TimeOut:=TickCount>timeOutTicks; until (TimeOut); position:=(StringToNum(response)/10); PutMessage('The Z-Axis is at Position:= ',position:7:1, ' microns. Note: (+) values are decreasing distance from objective to slide, (-) values are increasing distance.'); end; {Read Position} MACRO 'Move from Zero'; {Example of ABSOLUTE positioning} var MoveAmount,Microns,TenthsOfMicrons,NewPosition:string; i,j:integer begin Prefix:=06; Suffix:=07; Cmd1:=77; MoveAmount:=GetString('Enter Microns to Move from Zero: ','ie -10.5'); Microns:=MoveAmount; TenthsOfMicrons:=MoveAmount; i:=length(MoveAmount); {get string length} j:=pos('.',MoveAmount); {get position of decimal point} if j=0 the {if no decimal point add one and} begin {a 0 to right of string} TenthsOfMicrons:=Concat(MoveAmount,'.','0'); j:=i+1; {corrent decimal point position} i:=i+2; {correct string length} end; delete(TenthsOfMicrons,1,j); {Extract tenths of microns from string} delete(Microns,j,i); {Extract microns from input string} MoveAmount:=Concat(Microns,TenthsOfMicrons); {reassemble less decimal point} OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),MoveAmount,Chr(Suffix))); end; {Move from Zero} MACRO 'Move from Current Position'; {Example of RELATIVE positioning} var MoveAmount,Microns,TenthsOfMicrons:string; i,j:integer begin Prefix:=06; Suffix:=07; Cmd1:=73; { [I]ncremental Move Value to Store } Cmd2:=71; { [G]o to next (or first) increment } MoveAmount:=GetString('Enter Microns to Move from Current Position:','ie -10.0'); Microns:=MoveAmount; TenthsOfMicrons:=MoveAmount; i:=length(MoveAmount); {get string length} j:=pos('.',MoveAmount); {get position of decimal point} if j=0 then {if no decimal point add one & a 0 to right of string} begin TenthsOfMicrons:=Concat(MoveAmount,'.','0'); j:=i+1; {corrent decimal point position} i:=i+2; {correct string length} end; delete(TenthsOfMicrons,1,j); {Extract tenths of microns from string} delete(Microns,j,i);{Extract microns from input string} MoveAmount:=Concat(Microns,TenthsOfMicrons); {reassemble less decimal point} OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),MoveAmount,Chr(Cmd2),Chr(Suffix))); end; {Move from Current Position} MACRO 'Store Increment'; {Store an increment to move relative to current position} var MoveAmount,Microns,TenthsOfMicrons:string; i,j:integer begin Prefix:=06; Suffix:=07; Cmd1:=73; { [I]ncremental Move Value to Store } MoveAmount:=GetString('Enter Microns to Store:','ie -10.0'); Microns:=MoveAmount; TenthsOfMicrons:=MoveAmount; i:=length(MoveAmount); {get string length} j:=pos('.',MoveAmount); {get position of decimal point} if j=0 then {if no decimal point add one & a 0 to right of string} begin TenthsOfMicrons:=Concat(MoveAmount,'.','0'); j:=i+1; {corrent decimal point position} i:=i+2; {correct string length} end; delete(TenthsOfMicrons,1,j); {Extract tenths of microns from string} delete(Microns,j,i); {Extract microns from input string} MoveAmount:=Concat(Microns,TenthsOfMicrons); {reassemble less decimal point} OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),MoveAmount,Chr(Suffix))); end; {Store Increment} MACRO 'Go to Next Increment'; {Move the incremental amount that is stored} var MoveAmount:string; begin Prefix:=06; Suffix:=07; Cmd1:=71; { [G]o to next (or first) increment } OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),Chr(Suffix))); end; {Go to Next Increment} MACRO 'Stop'; {read current position - send it as new position} var TimeOutTicks,i,j:integer; position:real; character,response,MoveAmount:string Microns,TenthsOfMicrons,NewPosition:string; TimeOut:boolean; begin Prefix:=06; Suffix:=07; Cmd1:=82; { [R]eport Position Command} Cmd2:=77; { [M]ove to Position from Zero} RequiresVersion(1.50); OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd1),Chr(Suffix))); response:=''; TimeOutTicks:=TickCount+2; repeat character:=GetSerial; response:=Concat(response,character); TimeOut:=TickCount>timeOutTicks; until (TimeOut); OpenSerial('9600 baud,no parity,eight data,one stop'); PutSerial(Concat(Chr(Prefix),Chr(Cmd2),response,Chr(Suffix))); end; {Stop}