{ THIS CODE IS COPYRIGHT by Noel T Goldsmith,1st March 1993} {MT1NTG@ZODIAC.DSTO.GOV.AU} {DAFA Section, ARL 506 Lorimer Street, Port Melbourne, Victoria, 3207, AUSTRALIA} {Macro to control Marzhauser Stage using Multi Axis Controller (MAC) 4000.0} {MŠrzhŠser Wetzlar, An den Fichten, PostFach 2109, D-6330 Wetzlar 15} {Ph: (0011 49 ) 6441 24063, FAX (0015 49) 644124978} {The MAC 4000.0 is actually manufactured by Planungs and EntwicklungsbŸro} {JŸrgen Schiller, Rosengasse 5/ Sandgasse 13, 6330 Wetzlar} {Fax No (0015) 49 64 41 47 37 78} {Which is an RS232C serial port controlled microstepping controller for the stage.} {Plug the serial cable into the modem port. A suitable cable is an Apple mini-din 8 to 25 pin} {cable part number 590-0556-A which is a printer cable} {if you are using a Shiva-Net device on the network you may have to select none} {in the Shiva-Net setup control panel device for which port to emulate} { The version we have will drive three axes.} {The stage moves 1mm for 4000 full steps (0.25micron per full step)} { having 1mm pitch screws.} {The Z motor is linked to the focus knob and provides about 40 micron per 4000 steps} {or 0.01 micron per full step} { The operation of the device in a nutshell is as follows.} {The device self configures its serial communication parameters with any } {baud rate from 300 to 19,200, 7 or 8 data bits, 1 / 2 stop bits, parity being odd/even//none} {After switch on send two characters to it "O" and "o" (that is upper case letter O and } {lower case letter o), then wait a bit, and poll the port until you get a response} {Each response is terminated with a carriage return, unless you tell the termination } {register you want to use something else, I didn't bother yet} {The device will respond with its status, which is 3 numbers, one for each axis} {indicating whether it has hit the limit switches A (response 1) or B (response 2) } {or not response 0. Our controller has no limit switches on the Z axis (yet)} {therefore the possible responses are 000, 110, 220, 120, 210 , where the positions of } { the number refers to the x, y, and z axes respectively.} {The device has registers which may be read out with a read register command } {and registers which may be written into with a write register command.} {The device is controlled by sending it a command and waiting until it responds} {This response will be either a status or the contents of an axis. The axis contents } {may contain up to six numbers with a format of (Number:6:1), or 123456.7} {The maximum number of steps is 999999, but I know it will move 0.1 steps} {This aspect is being clarified} {The motions may not be negative, so all motion is in one quadrant, just like the} {screen of a Macintosh, the coordinate system is even the same, looking} {down on the stage from above. A calibrate command moves the axes to 0,0} {which corresponds to the top left} {This may be immediately or take some time if a calibration is being done (>=10 seconds} {There are several kinds of register. These include axis position registers, command} {registers and control of state registers. There are two kinds of axis position registers.} {Desired position registers and Actual position registers, The desired position register} {is loaded with the position to which the axis is to be moved to, and the Actual } {position register contains the value of the current position} {The stage is moved by loading up the desired position registers with the } {desired position and then sending the command instruction followed by the vector} {pass command followed by a return followed by an execute instruction.} {The stage may be moved with the joystick and then have the zero position set at } {the point where motion is stopped} {The command register may contain up to 7 separate instructions which will be} {executed on receipt of an execution instruction} {Now you know enough to read the manual and do some things yourself} {What follows is my beginning attempt to make the MAC 4000.0 do useful things} {The macro code defines a set of variable which are used to provide a higher level } {interface to the controller than the primitives (single numerals or characters) } {which the controller needs. A number of different procedures are used to allow the} {use of operations such as read axes, use joystick, set axes, raster and so-on} {The macro provides output in the results window, and will prompt the user} {to press the mouse button to continue} {THINGS TO ADD. HANDLING OF ERRORS PRODUCED BY HITTING LIMITS} {USE STATUS CODE FOR THIS, ALLOW USER TO RECOVER GRACEFULLY} {This code is provided as-is and no warranty is implied or intended that it will actually} {do anything, It is an example provided for the education of the reader} {Any positive feedback would be appreciated MT1NTG@ZODIAC.DSTO.GOV.AU} {GLOBAL VARIABLE LIST} var ch,register,resp,return,message,command:string; Status,Execute,Stop,Init:string; ReadXDes,ReadYDes,ReadZDes,ReadXAct,ReadYAct,ReadZAct:string; WriteXDes,WriteYDes,WriteZDes,WriteXAct,WriteYAct,WriteZact:string; ReadCommand,ReadFunction,ReadTermin,ReadCharDel,ReadSwitDel:String; WriteCommand,WriteFunction,WriteTermin,WriteCharDel,WriteSwitDel:string; ReadPathImpR,ReadMask,ReadSpeedTab,ReadAbsSpeed:string; WritePathImpR,WriteMask,WriteSpeedTab,WriteAbsSpeed:string; Calibrate,MaxTravel,JoyWith,JoyWithOut,VectorIn,VectorEx,SetPosition,Naught:string; XPos,YPos,ZPos,XStepSize,YStepSize,ZStepSize:Real; XSteps,YSteps,ZSteps:real; XAct,YAct,ZAct:string; XCount,YCount,ZCount:Integer; procedure GetResponse(response:string); begin response:=''; repeat ch:=GetSerial; {ShowMessage(Concat('Character is :',ch,return));} response:=Concat(response,ch); {ShowMessage(Concat('Response is:',response,return));} until ch=return; {ShowMessage(Concat('Final Response is: ',return,response,return));} resp:=response; {wait(.5);} end; Procedure ReadRegister(Register:string); begin PutSerial(Register); end; Procedure WriteRegister(Register:string); begin PutSerial(Register); end; Procedure WriteRegResp(Register:string); begin PutSerial(Register); repeat until button; WriteRegister(Stop); end; Procedure DoCommand(Command:string); begin PutSerial(Command); end; Procedure UseJoystick; {lets user move to a wanted position} begin {With Actual Position Updates} PutMessage('Use joystick to move stage to desired position, press mouse when ready'); WriteRegResp(Concat(WriteCommand,JoyWith,return,Execute)); {GetResponse(message);} repeat until button; {This operation must be stopped} WriteRegister(Stop); {the mouse button press activates this} GetResponse(Message); end; Procedure UseJoystickNU; {No Position updates} begin PutMessage('Use joystick to move stage to desired position, press mouse when ready'); WriteRegResp(Concat(WriteCommand,JoyWithOut,return,Execute)); {GetResponse(message);} repeat until button; WriteRegister(Stop); GetResponse(Message); end; procedure SetAxes; {Sets axes to zero at the place where they are} {, ie after joystick use or a vector pass} begin WriteRegister(Concat(WriteCommand,SetPosition,return,Execute)); GetResponse(command); end; Procedure READAXES; begin ReadRegister(ReadXAct); GetResponse(resp); Xact:=resp; readregister(ReadYAct); GetResponse(resp); YAct:=resp; ReadRegister(ReadZAct); GetResponse(resp); Zact:=resp; ShowMessage(Concat('Xactual is ',Xact:6:1,'Yactual is ',YAct:6:1,'Zactual is ',ZAct:6:1,return,'press mouse to continue')); repeat until button; end; Procedure MOVEAxesTO; begin WriteRegister(Concat(WriteCommand,VectorIn,return,Execute)); GetResponse(message); end; Procedure SetUpRaster; begin XSteps:=GetNumber('Input Number of Steps Across ',5); YSteps:=GetNumber('Input Number of Steps Up ',4); XstepSize:=GetNumber('Input Size of Steps Across mm ',5); XStepSize:=XStepSize*4000; YstepSize:=GetNumber('Input Size of Steps Up mm ',5); YStepSize:=YStepSize*4000; end; Procedure raster; begin For Ycount:=1 to Ysteps do begin for Xcount := 1 to XSteps do begin XPos:=Xcount *XStepSize; YPos:=Ycount *YStepSize; WriteRegister(Concat(WriteXDes,XPos,return)); WriteRegister(Concat(WriteYDes,YPos,return)); WriteRegister(Concat(WriteCommand,VectorIn,return,Execute)); GetResponse(message); end; end; end; Macro 'MARZHAUSER TEST[M]'; begin {define variables for controlling stage} Status:='f'; Execute:='p'; Stop:='q'; Init:='r'; ReadXDes:=' '; ReadYDes:='a'; ReadZDes:='b'; ReadXAct:='c'; ReadYAct:='d'; ReadZAct:='e'; WriteXDes:='@'; WriteYDes:='A'; WriteZDes:='B'; WriteXAct:='C'; WriteYAct:='D'; WriteZact:='D'; ReadCommand:='g'; ReadFunction:='h'; ReadTermin:='i'; ReadCharDel:='j'; ReadSwitDel:='k'; WriteCommand:='G'; WriteFunction:='H'; WriteTermin:='I'; WriteCharDel:='J'; WriteSwitDel:='K'; ReadPathImpR:='l'; ReadMask:='m'; ReadSpeedTab:='n'; ReadAbsSpeed:='o'; WritePathImpR:='L'; WriteMask:='M'; WriteSpeedTab:='N'; WriteAbsSpeed:='O'; Calibrate:='0'; MaxTravel:='1'; JoyWith:='2'; JoyWithOut:='3'; VectorIn:='4'; VectorEx:='5'; SetPosition:='6'; Naught:='7'; {non-active command may be used to do nothing} return:=Chr(13); resp:='Original'; message:='mess'; XStepSize:=4000; YStepSize:=4000; ZStepSize:=4000; XSteps:=10; YSteps:=10; ZSteps:=10; PutMessage('Turn on Stage Controller and press mouse after 5 seconds'); repeat until button; OpenSerial('9600 baud, no parity, eight data, two stop'); PutSerial(Concat('O','o')); Wait(1); {This is in original Marzhauser code} Repeat Until GetSerial=''; ReadRegister(status); showMessage('first get response follows'); wait(1); GetResponse(message); ShowMessage(Concat('Message received is: ',return,'resp ',resp)); Wait(.1); Register:=Concat(WriteMask,'1','1','2',return); {Write 112 into Mask} ShowMessage(Concat('String being sent is ',Register)); Wait(.1); WriteRegister(Register); ReadRegister(ReadMask); GetResponse(message); ShowMessage(Concat('Message received is: ',resp)); Wait(.1); ShowMessage('Now moving to 0,0,0 '); Wait(1); XPos:=0;Ypos:=0;Zpos:=0; WriteRegister(Concat(WriteXDes,Xpos,return)); WriteRegister(Concat(WriteYDes,Ypos,return)); WriteRegister(Concat(WriteZDes,Zpos,return)); WriteRegister(Concat(WriteCommand,Calibrate,return,Execute)); GetResponse(message); UseJoystick; readaxes; SetAxes; readAxes; MOVEAxesTO; UseJoystick; readaxes; SetAxes; readaxes; MOVEAxesTO; Readaxes; SetUpRaster; Raster; {This will just move the stage, you may want to do something} {at each position.} ShowMessage('Program Finished'); end; Macro 'InitMarz'; {this is the minimum for starting to talk to the controller} begin OpenSerial('9600 baud, no parity, eight data, two stop'); PutSerial(Concat('O','o')); Wait(1); Repeat Until GetSerial=''; ReadRegister(status); GetResponse(message); ShowMessage(Concat('Status of Controller is: ',resp,return,' Press Mouse to Exit')); Repeat Until Button; ShowMessage('Program Finished'); end;