Go to the documentation of this file.00001 CLOSE
00002
00003 ;###############################################
00004 ; Define motion for Energy in Diamond QCM
00005 ; Original Author: Pete Leicester
00006 ; Defined axes:
00007 ; X (addr 6) = Energy1 in kEv
00008 ; Y (addr 7) = EnergyOffset in kEv
00009 ; Z (addr 8) = Energy2 in kEv
00010 ; Macros (and example values):
00011 ; COORD - CS number (only works for CS 1..9), e.g. 2
00012 ; PLC - PLC number, should be CS number+15, e.g. 17
00013 ; BRAGG1 - Axisnum for Bragg1, e.g. 2
00014 ; BRAGG2 - Axisnum for Bragg2, e.g. 3
00015 ; RADMRES1 - resolution for bragg1 (NB keep sign same as real bragg1 motor MRES)
00016 ; RADMRES2 - resolution for bragg2 (NB keep sign same as real bragg2 motor MRES)
00017 ; (Note1 the real bragg1/2 motors can have any resolution/unit desired
00018 ; so can be in steps, degrees or rad (if set the same as RADMRES))
00019 ; (Note2 remember to increase the resolution by *32 to match the pmacSetAxisScale(3,1,32)
00020 ; calls in the start up file)
00021 ;
00022 ; Additional controls that could be changed from EPIC's
00023 ; Q20 - Mode (0= energy and offset, 1= two independent energy axis)
00024 ;
00025 ; Readbacks for epics
00026 ; Q21 - crystal spacing (3.13475 for Si(111), 1.637069796 for Si(311)). Value defined by switch wired to pmac input.
00027 ;
00028 ;################################################
00029
00030 ; Change to CS$(COORD)
00031 &$(COORD)
00032
00033 ; Set relevant axes to use kinematics
00034 #$(BRAGG1)->I
00035 #$(BRAGG2)->I
00036
00037 ; These are set by motor_in_cs.template
00038 #define B1MOVE P(4700+$(BRAGG1))
00039 #define B1MRES P(4800+$(BRAGG1))
00040 #define B1OFF P(4900+$(BRAGG1))
00041 #define B2MOVE P(4700+$(BRAGG2))
00042 #define B2MRES P(4800+$(BRAGG2))
00043 #define B2OFF P(4900+$(BRAGG2))
00044
00045 ; Mode of operation
00046 ; 0 = Energy and EnergyOffset compound motors (i.e. bragg2=bragg1+offset)
00047 ; 1 = Independent energy axis (i.e. independent bragg1 and bragg2)
00048 ; define default value for epics to overwrite
00049 #define MODE Q20
00050 MODE=0
00051
00052 ; Setup energy calculation variables
00053 ; Energy in keV = {Evlamda}/(2*{d}*sin(Bragg))
00054 ; where Bragg is in rad's
00055 ; Evlamda = 12.3985
00056 ; d = crystal spacing in angstrom (dependent on temperature)
00057 ; d (at room temp) = 5.430845307 / sqrt(h^2+k^2+l^2) and h,k,l = 1,1,1 or 3,1,1 depending on silicon type
00058 ; d (at room temp) = 3.1355 for Si(111)
00059 ; d (at room temp) = 1.637461471 for Si(311)
00060 ; d (at liguid N2 temp) = 5.429546269 / sqrt(h^2+k^2+l^2) and h,k,l = 1,1,1 or 3,1,1 depending on silicon type
00061 ; d (at liguid N2 temp) = 3.13475 for Si(111)
00062 ; d (at liguid N2 temp) = 1.637069796 for Si(311)
00063 ; { This boils down to at room temp
00064 ; Energy in keV = 1.977116887 / sin(Bragg) for Si(111)
00065 ; or Energy in keV = 3.785890606 / sin(Bragg) for Si(311)
00066 ; and at liguid N2 temp
00067 ; Energy in keV = 1.977589919 / sin(Bragg) for Si(111)
00068 ; or Energy in keV = 3.786796394 / sin(Bragg) for Si(311) }
00069 ;
00070
00071 ; Define d = crystal spacing in angstrom Si(111) (default value for switch input to overwrite)
00072 #define DSPACING Q21
00073 DSPACING=3.13475
00074
00075 ; Define Evlambda
00076 #define EVLAMBDA Q22
00077 EVLAMBDA=12.3985
00078
00079 ; Q23 is used for debugging - value indicates where last error occurred in kinematic
00080 #define ERRORLOC Q23
00081
00082 #define LASTMODE Q24
00083 LASTMODE=MODE
00084
00085 #define LASTDSPACING Q25
00086 LASTDSPACING=DSPACING
00087
00088 ; This kinematic is for the QCM energy in kEv
00089 ; X = Q7 = Energy1 in kEv = {Evlamda}/(2*{d}*sin(Bragg1))
00090 ; Y = Q8 = EnergyOffset in kEv = Energy1 - Energy2
00091 ; = Energy1 - {Evlamda}/(2*{d}*sin(Bragg2))
00092 ; Z = Q9 = Energy2 in kEv = {Evlamda}/(2*{d}*sin(Bragg2))
00093 #define B1POS ($(RADMRES1)*(P$(BRAGG1)+(B1OFF/(B1MRES*32))))
00094 #define B2POS ($(RADMRES2)*(P$(BRAGG2)+(B2OFF/(B2MRES*32))))
00095 #define ENERGY1 Q7
00096 #define EOFFSET Q8
00097 #define ENERGY2 Q9
00098 #define SETERROR M(100*$(COORD)+5082)=1
00099 ; Local variables
00100 #define NLAMBDA1 Q128
00101 #define NLAMBDA2 Q129
00102 OPEN FORWARD
00103 CLEAR
00104 NLAMBDA1=2*DSPACING*SIN(B1POS)
00105 NLAMBDA2=2*DSPACING*SIN(B2POS)
00106 IF (ABS(NLAMBDA1)>0.0001)
00107 ENERGY1=EVLAMBDA/NLAMBDA1
00108 IF (ABS(NLAMBDA2)>0.0001)
00109 ENERGY2=EVLAMBDA/NLAMBDA2
00110 IF(MODE=0)
00111 EOFFSET=ENERGY2-ENERGY1
00112 ENDIF
00113 ELSE
00114 SETERROR
00115 ERRORLOC=4
00116 ENDIF
00117 ELSE
00118 SETERROR
00119 ERRORLOC=5
00120 ENDIF
00121 CLOSE
00122
00123 ; Calculate Bragg from Energy and Offset
00124 ; P$(BRAGG1) = Bragg1 position = arcsin({Evlamda}/(2*{d}*(Energy1))
00125 ; P$(BRAGG2) = Bragg2 position = arcsin({Evlamda}/(2*{d}*(Energy2))
00126 ; where Energy2 = Energy1(Q7) - EnergyOffset(Q8)
00127 ; or Bragg2 position = arcsin({Evlamda}/(2*{d}*(Energy2))
00128 #define B1POS Q228
00129 #define B2POS Q229
00130 #define SINTHETA1 Q230
00131 #define SINTHETA2 Q231
00132
00133 OPEN INVERSE
00134 CLEAR
00135 SINTHETA1=EVLAMBDA/(2*DSPACING*ENERGY1)
00136 IF (ABS(SINTHETA1)<1)
00137 ; calculate bragg1 in EGUs
00138 B1POS = asin(SINTHETA1)
00139 ; then in cts
00140 P$(BRAGG1)=(B1POS/$(RADMRES1))-(B1OFF/(B1MRES*32))
00141 IF (MODE=0)
00142 SINTHETA2=EVLAMBDA/(2*DSPACING*(ENERGY1+EOFFSET))
00143 IF (ABS(SINTHETA2)<1)
00144 ; calculate bragg1 in EGUs
00145 B2POS = asin(SINTHETA2)
00146 ; then in cts
00147 P$(BRAGG2)=(B2POS/$(RADMRES2))-(B2OFF/(B2MRES*32))
00148 ELSE
00149 SETERROR
00150 ERRORLOC=1
00151 ENDIF
00152 ELSE
00153 SINTHETA2=EVLAMBDA/(2*DSPACING*ENERGY2)
00154 IF (ABS(SINTHETA2)<1)
00155 ; calculate bragg1 in EGUs
00156 B2POS = asin(SINTHETA2)
00157 ; then in cts
00158 P$(BRAGG2)=(B2POS/$(RADMRES2))-(B2OFF/(B2MRES*32))
00159 ELSE
00160 SETERROR
00161 ERRORLOC=2
00162 ENDIF
00163 ENDIF
00164 ELSE
00165 SETERROR
00166 ERRORLOC=3
00167 ENDIF
00168 CLOSE
00169
00170 ; A PLC(sx+15) needs to be made to do position reporting
00171 ; Readbacks should be in &{axisnum}Q81..89
00172 ; As forward kinematic, but with Px = mx62/(Ix08*32) and no error reporting
00173 #define B1POS ($(RADMRES1)*(m$(BRAGG1)62/(I$(BRAGG1)08*32)+(B1OFF/(B1MRES*32))))
00174 #define B2POS ($(RADMRES2)*(m$(BRAGG2)62/(I$(BRAGG2)08*32)+(B2OFF/(B2MRES*32))))
00175 #define ENERGY1 Q87
00176 #define EOFFSET Q88
00177 #define ENERGY2 Q89
00178 ; Local variables
00179 #define NLAMBDA1 Q328
00180 #define NLAMBDA2 Q329
00181 OPEN PLC $(PLC)
00182 CLEAR
00183 ADDRESS&$(COORD)
00184 NLAMBDA1=2*DSPACING*SIN(B1POS)
00185 NLAMBDA2=2*DSPACING*SIN(B2POS)
00186 IF (ABS(NLAMBDA1)>0.0001)
00187 ENERGY1=EVLAMBDA/NLAMBDA1
00188 IF (ABS(NLAMBDA2)>0.0001)
00189 ENERGY2=EVLAMBDA/NLAMBDA2
00190 EOFFSET=ENERGY2-ENERGY1
00191 ENDIF
00192 ENDIF
00193 ; If bragg motor record did the last move, set demands = readbacks
00194 if (B1MOVE = 1)
00195 or (B2MOVE = 1)
00196 B1MOVE = 0
00197 B2MOVE = 0
00198 Q77 = Q87
00199 Q78 = Q88
00200 Q79 = Q89
00201 endif
00202 ; if mode or crystal spacing has changed then set demands = readback to
00203 ; prevent undesired moves
00204 if (MODE!=LASTMODE)
00205 or (DSPACING!=LASTDSPACING)
00206 Q77 = Q87
00207 Q78 = Q88
00208 Q79 = Q89
00209 LASTMODE=MODE
00210 LASTDSPACING=DSPACING
00211 endif
00212 CLOSE
00213 ENABLE PLC $(PLC)
00214
00215
00216 ;################################################
00217 ; Note on calibrating the energy in EPICS
00218 ; In order to correct the energy readback value linearly across the whole range
00219 ; of bragg it is necessary to adjust the EPICS motor offset of the real bragg
00220 ; motors BRAGG1 and BRAGG2. The resolution of these motors is defined by B1MRES
00221 ; and B2MRES.
00222 ; Therefore (if 'actual' is what it should read and 'readback' is the current energy value generated by the PLC):
00223 ; epics offset correction(real b1 mtr) = ( ( bragg1(actual in rad) - bragg1(readback in rad) ) / RADMRES1 ) * B1MRES * 32
00224 ; epics offset correction(real b2 mtr) = ( ( bragg2(actual in rad) - bragg2(readback in rad) ) / RADMRES2 ) * B2MRES * 32
00225 ; and
00226 ; bragg1 in rad = arcsin( Evlambda / ( 2d * Energy1(kEv) ) )
00227 ; bragg2 in rad = arcsin( Evlambda / ( 2d * Energy2(kEv) ) )
00228 ;
00229 ;################################################
00230