Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/BraggGapMono.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions docs/opticsDocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ synApps supports the following monochromator types/geometries:

- non-dispersive double-crystal with symmetric offset -- rotates about a point midway between the entrance and exit beams.
- non-dispersive double-crystal with asymmetric offset -- rotates about a point on the first crystal's surface.
- non-dispersive double-crystal with bragg and gap control -- rotates about point on first crystal's surface; two motors (bragg, gap)
- dispersive double crystal -- nested geometry
- dispersive double crystal -- symmetric geometry
- spherical grating
Expand Down Expand Up @@ -109,6 +110,16 @@ Thus, a positive-sense motion of the second crystal moves it in the direction of

Because the Y and Z motions are nonlinear functions of Theta, their speeds ideally should vary as they move. The software doesn't attempt this, but it does attempt to set motor speeds to the closest linear approximation to ideal behavior. This means that it attempts to set motor speeds so that Theta, Y, and Z all move for the same length of time. The attempt may not succeed, however, because the motors have high and low speed limits, and will refuse commands to violate them.

### Bragg-Gap (Theta, Y)

#### bragg_gap_mono_main.ui

![](BraggGapMono.jpg)

Similar to Kohzu Geometry 2 with Z-frozen. However, relies on pseudomotors and DB programming instead of SNL to handle motion/limits.

The monochromator can be driven in energy, wavelength, or angle. Undriven fields are kept consistent automatically with driven fields.


### High-resolution double-crystal (Theta1, Theta2)

Expand Down
38 changes: 38 additions & 0 deletions iocBoot/iocAny/pseudoMotor_monos.substitutions
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# EPICS-based replacement for energy and offset pseudo positioners needed
# to drive Axilon monochromators

file "$(MOTOR)/motorApp/Db/pseudoMotor.db"
{
pattern
{M, DINP, OUT, RDBL, STOO, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, RRES, PREC, DHLM, DLLM}
{Bragg, "$(P)EO:Done NPP NMS", "$(P)BraggDVAL.VAL PP MS", "$(P)EO:Readback.L NPP NMS", "$(P)EO:Stop PP MS", "DCM Bragg PM", degrees,Pos, 1, .1, .1, 0, 1, .1, .00001, 1.0, 6, 0, 0}
{Gap, "$(P)EO:Done NPP NMS", "$(P)GapDVAL.VAL PP MS", "$(P)EO:Readback.M NPP NMS", "$(P)EO:Stop PP MS", "DCM Gap PM", um, Pos, 1, .1, .1, 0, 1, .1, .001, 1.0, 6, 0, 0}
{Energy, "$(P)EO:Done NPP NMS", "$(P)EnergyDVAL.VAL PP MS", "$(P)EO:Readback.F NPP NMS", "$(P)EO:Stop PP MS", "DCM Energy", keV, Pos, 1, .1, .1, 0, 1, .1, .00001, 1.0, 6, 0, 0}
{Offset, "$(P)EO:Done NPP NMS", "$(P)OffsetDVAL.VAL PP MS", "$(P)EO:Readback.K NPP NMS", "$(P)EO:Stop PP MS", "DCM Offset", um, Pos, 1, .1, .1, 0, 1, .1, .001, 1.0, 6, 0, 0}
{Lambda, "$(P)L:Done NPP NMS", "$(P)LambdaDVAL.VAL PP MS", "$(P)L:Readback.G NPP NMS", "$(P)L:Stop PP MS", "DCM Wavelength", Angstrom, Pos, 1, .1, .1, 0, 1, .1, .00001, 1.0, 6, 0, 0}
}

# TransformEnergy provides an Energy positioner. The energy pseudopositioner
# also supports fixed-offset mode.
#
# ENERGY: energy pseudomotor
# Offset: offset pseudomotor
# OFFSET_BINARY: binary PV indicating if fixed offset mode is on (1) or off (0)

file "$(TOP)/db/transformEBO.db"
{
pattern
{T, BRAGG_PM, GAP_PM, ENERGY, OFFSET, OFFSET_BINARY, BRAGG_MOT, GAP_MOT, PREC}
{"EO:", "Bragg", "Gap", "Energy", "Offset", "$(P)offset_mode", "$(BRAGG_HM)", "$(GAP_HM)", 8}
}

# TransformLambda provides an wavelength (lambda) positioner.
#
# LAMBDA: energy pseudomotor

file "$(TOP)/db/transformLambda.db"
{
pattern
{T, LAMBDA, ENERGY_DRV, ENERGY_RBV, ENERGY_STOP, ENERGY_DONE, ENERGY_LO, ENERGY_HI, PREC}
{"L:", Lambda, "$(P)Energy.VAL", "$(P)Energy.RBV", "$(P)Energy.STOP", "$(P)Energy.DMOV", "$(P)Energy.DLLM", "$(P)Energy.DHLM", 8}
}
20 changes: 20 additions & 0 deletions iocBoot/iocAny/simpleMono.iocsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
########################################################################
#
# PREFIX - IOC prefix
# INSTANCE - mono instancne
# BRAGGMOTOR - bragg motor
# GAPMOTOR - gap motor
#
########################################################################

########################################################################
# Mono Energy positioner and offset mode implmentation
########################################################################

# Load mono records
dbLoadRecords("$(TOP)/db/monoModes.db","P=$(PREFIX), MN=$(INSTANCE), GAP=$(GAPMOTOR), BRAGG=$(BRAGGMOTOR), ENERGY=$(ENERGY=Energy)")

# Load pseudo-motor records
dbLoadTemplate("pseudoMotor_monos.substitutions","P=$(PREFIX)$(INSTANCE):,BRAGG_HM=$(BRAGGMOTOR),GAP_HM=$(GAPMOTOR)")


3 changes: 3 additions & 0 deletions iocBoot/iocAny/st.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ iocxxxLinux_registerRecordDeviceDriver(pdbbase)
## VMAS (white beam slits)
iocshLoad("$(OPTICS)/opticsApp/iocsh/vmas.iocsh", "P=$(PREFIX),S=slits,HORIZONTAL=m1,DIAGONAL=m2,PITCH=m3,YAW=m4")

# Simple mono (Bragg and Gap) - Creates energy and offset positioners
iocshLoad("simpleMono.iocsh", "PREFIX=$(PREFIX), INSTANCE=MN1, BRAGGMOTOR=$(PREFIX)m1, GAPMOTOR=$(PREFIX)m2")

### soft motor slits
dbLoadRecords("$(OPTICS)/opticsApp/Db/2slit_soft.vdb","P=xxx:,SLIT=Slit2V,mXp=m3,mXn=m4")
dbLoadRecords("$(OPTICS)/opticsApp/Db/2slit_soft.vdb","P=xxx:,SLIT=Slit2H,mXp=m5,mXn=m6")
Expand Down
257 changes: 257 additions & 0 deletions opticsApp/Db/monoModes.db
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
################################################################################
# Miller indices (H,K,L) -- using same convention as Optics' Kohzu support

record(ao,"$(P)$(MN):BraggHAO") {
field(DESC,"Miller index H")
field(PINI,"YES")
field(DOL,"1")
field(DRVH,"15")
field(DRVL,"0")
field(HOPR,"15")
field(LOPR,"0")
}
record(ao,"$(P)$(MN):BraggKAO") {
field(DESC,"Miller index K")
field(PINI,"YES")
field(DOL,"1")
field(DRVH,"15")
field(DRVL,"0")
field(HOPR,"15")
field(LOPR,"0")
}
record(ao,"$(P)$(MN):BraggLAO") {
field(DESC,"Miller index L")
field(PINI,"YES")
field(DOL,"1")
field(DRVH,"15")
field(DRVL,"0")
field(HOPR,"15")
field(LOPR,"0")
}
record(ao,"$(P)$(MN):BraggAAO") {
field(DESC,"Lattice constant")
field(PINI,"YES")
field(DOL,"5.43102")
field(PREC,"5")
field(EGUF,"20")
field(EGUL,"0.1")
field(EGU,"Angstroms")
field(DRVH,"20")
field(DRVL,"0.1")
field(HOPR,"20")
field(LOPR,"0.1")
}

record(ao,"$(P)$(MN):Bragg2dSpacingAO") {
field(DESC,"Crystal 2d spacing")
field(PINI,"YES")
field(DOL,"1")
field(PREC,"5")
field(EGU,"Angstroms")
}

record(calcout,"$(P)$(MN):dspacing_calc") {
field(DESC,"Update offset boolean")
field(INPA, "$(P)$(MN):Bragg2dSpacingAO CP")
field(CALC, "A/2")
field(OUT, "$(P)$(MN):dspacing PP")
field(PREC,"5")
}

record(ao, "$(P)$(MN):dspacing") {
field(DESC, "D-spacing")
field(EGU, "Angstroms")
field(OUT, "$(P)$(MN):$(ENERGY)C1 PP")
field(PREC, "6")
}


record(transform,"$(P)$(MN):calc2dSpacing") {
field(INPA,"$(P)$(MN):BraggHAO CP NMS")
field(CMTA,"Miller index H")
field(INPB,"$(P)$(MN):BraggKAO CP NMS")
field(CMTB,"Miller index K")
field(INPC,"$(P)$(MN):BraggLAO CP NMS")
field(CMTC,"Miller index L")
field(INPD,"$(P)$(MN):BraggAAO CP NMS")
field(CMTD,"Lattice Constant")
field(CMTE,"")
field(CLCE,"")
field(OUTE,"")
field(CMTF,"")
field(CLCF,"((A%2 != B%2) || (A%2 != C%2))?1:0")
field(OUTF,"")
field(CMTG,"Average Miller index")
field(CLCG,"(A+B+C)/2.0")
field(OUTG,"")
field(CMTH,"Nearest integer to average")
field(CLCH,"NINT(G)")
field(OUTH,"")
field(CMTI,"Forbidden Reflection")
field(CLCI,"(F || ((ABS(G-H) <= 0.25) && (H%2)))?1:0")
field(OUTI,"$(P)$(MN):forbidden_reflection PP")
field(CMTJ,"2D spacing")
field(CLCJ,"(2*D)/sqrt(A*A+B*B+C*C)")
field(OUTJ,"$(P)$(MN):Bragg2dSpacingAO PP")
field(PREC,"8")
}

record(bi, "$(P)$(MN):forbidden_reflection") {
field(DESC, "Forbidden reflection")
field(ZNAM, "Valid")
field(ONAM, "Forbidden")
}

################################################################################
# TODO check that wavelength is shorter than d-spacing
record(bi, "$(P)$(MN):forbidden_wavelength") {
field(DESC, "Wavelength too long")
field(ZNAM, "Valid")
field(ONAM, "Invalid")
}

record(calcout,"$(P)$(MN):check_lambda") {
field(DESC,"Update validity boolean")
field(INPA, "$(P)$(MN):Bragg2dSpacingAO CP")
field(INPB, "$(P)$(MN):Lambda CP")
field(CALC, "B>A?1:0")
field(OUT, "$(P)$(MN):forbidden_wavelength PP")
}

record(bo,"$(P)$(MN):offset_mode") {
field(DESC,"Offset mode")
field(ZNAM,"Fixed Offset")
field(ONAM,"Channel-cut")
field(VAL, "1")
}

record(mbbo,"$(P)$(MN):crystal_mode") {
field(DESC,"Crystal choice")
field(ZRVL,"0x0")
field(ONVL,"0x1")
field(TWVL,"0x2")
field(THVL,"0x3")
field(FRVL,"0x4")
field(FVVL,"0x5")
field(SXVL,"0x6")
field(SVVL,"0x7")
field(EIVL,"0x8")
field(NIVL,"0x9")
field(TEVL,"0xA")
field(ELVL,"0xB")
field(TVVL,"0xC")
field(TTVL,"0xD")
field(FTVL,"0xE")
field(FFVL,"0xF")
field(ZRST,"Silicon")
field(ONST,"Germanium")
field(TWST,"Diamond")
field(THST,"Si (77K)")
field(FRST,"Unused")
field(FVST,"Unused")
field(SXST,"Unused")
field(SVST,"Unused")
field(EIST,"Unused")
field(NIST,"Unused")
field(TEST,"Unused")
field(ELST,"Unused")
field(TVST,"Unused")
field(TTST,"Unused")
field(FTST,"Unused")
field(FFST,"Unused")
field(FLNK, "$(P)$(MN):LatticeConstants.PROC")
# TODO May need to process LatticeConstants PV?
field(PINI, "YES")
}

record(seq,"$(P)$(MN):LatticeConstants") {
field(SELM,"Specified")
field(SELL,"$(P)$(MN):crystal_mode NPP NMS")
field(PREC,"7")
field(DO0,"5.4310196")
field(LNK0,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO1,"5.657952")
field(LNK1,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO2,"3.56688")
field(LNK2,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO3,"5.4295")
field(LNK3,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO4,"5.4310196")
field(LNK4,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO5,"5.657952")
field(LNK5,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO6,"3.56688")
field(LNK6,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO7,"5.4295")
field(LNK7,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO8,"5.4310196")
field(LNK8,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DO9,"5.657952")
field(LNK9,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DOA,"3.56688")
field(LNKA,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DOB,"5.4295")
field(LNKB,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DOC,"5.4310196")
field(LNKC,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DOD,"5.657952")
field(LNKD,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DOE,"3.56688")
field(LNKE,"$(P)$(MN):BraggAAO.VAL PP MS")
field(DOF,"5.4295")
field(LNKF,"$(P)$(MN):BraggAAO.VAL PP MS")

}
# use calcout to store/set lattice constant ?


# Calibration -- need "cross-checks" for putting system/motors into USE/SET mode
record(bo,"$(P)$(MN):UseSet") {
field(DESC,"Put motors in Use/Set mode")
field(ZNAM,"Use")
field(ONAM,"Set")
}

record(calcout,"$(P)$(MN):UseSet_sysBragg") {
field(DESC,"Update Use-Set boolean")
field(INPA, "$(P)$(MN):UseSet CP")
field(INPB, "$(BRAGG).SET NPP")
field(CALC, "A!=B")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "A")
field(OUT, "$(BRAGG).SET PP")
}

record(calcout,"$(P)$(MN):UseSet_sysGap") {
field(DESC,"Update Use-Set boolean")
field(INPA, "$(P)$(MN):UseSet CP")
field(INPB, "$(GAP).SET NPP")
field(CALC, "A!=B")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "A")
field(OUT, "$(GAP).SET PP")
}

record(calcout,"$(P)$(MN):UseSet_braggSys") {
field(DESC,"Update Use-Set boolean")
field(INPA, "$(BRAGG).SET CP")
field(INPB, "$(P)$(MN):UseSet NPP")
field(CALC, "A!=B")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "A")
field(OUT, "$(P)$(MN):UseSet PP")
}

record(calcout,"$(P)$(MN):UseSet_gapSys") {
field(DESC,"Update Use-Set boolean")
field(INPA, "$(GAP).SET CP")
field(INPB, "$(P)$(MN):UseSet NPP")
field(CALC, "A!=B")
field(OOPT, "When Non-zero")
field(DOPT, "Use OCAL")
field(OCAL, "A")
field(OUT, "$(P)$(MN):UseSet PP")
}
38 changes: 38 additions & 0 deletions opticsApp/Db/monoModes_settings.req
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
$(P)$(MN):offset_mode
$(P)$(MN):crystal_mode
$(P)$(MN):crystal_mode.ZRST
$(P)$(MN):crystal_mode.ONST
$(P)$(MN):crystal_mode.TWST
$(P)$(MN):crystal_mode.THST
$(P)$(MN):crystal_mode.FRST
$(P)$(MN):crystal_mode.FVST
$(P)$(MN):crystal_mode.SXST
$(P)$(MN):crystal_mode.SVST
$(P)$(MN):crystal_mode.EIST
$(P)$(MN):crystal_mode.NNST
$(P)$(MN):crystal_mode.TNST
$(P)$(MN):crystal_mode.ELST
$(P)$(MN):crystal_mode.TVST
$(P)$(MN):crystal_mode.TTST
$(P)$(MN):crystal_mode.FTST
$(P)$(MN):crystal_mode.FFST
$(P)$(MN):LatticeConstants.DO0
$(P)$(MN):LatticeConstants.DO1
$(P)$(MN):LatticeConstants.DO2
$(P)$(MN):LatticeConstants.DO3
$(P)$(MN):LatticeConstants.DO4
$(P)$(MN):LatticeConstants.DO5
$(P)$(MN):LatticeConstants.DO6
$(P)$(MN):LatticeConstants.DO7
$(P)$(MN):LatticeConstants.DO8
$(P)$(MN):LatticeConstants.DO9
$(P)$(MN):LatticeConstants.DOA
$(P)$(MN):LatticeConstants.DOB
$(P)$(MN):LatticeConstants.DOC
$(P)$(MN):LatticeConstants.DOD
$(P)$(MN):LatticeConstants.DOE
$(P)$(MN):LatticeConstants.DOF
$(P)$(MN):BraggHAO
$(P)$(MN):BraggKAO
$(P)$(MN):BraggLAO
$(P)$(MN):BraggAAO
Loading
Loading