CS_QCM.pmc

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 
 All Classes Files Functions Variables Typedefs Defines