diff --git a/src/dodal/beamlines/i16.py b/src/dodal/beamlines/i16.py new file mode 100644 index 00000000000..2695be006b2 --- /dev/null +++ b/src/dodal/beamlines/i16.py @@ -0,0 +1,25 @@ +from dodal.common.beamlines.beamline_utils import device_factory +from dodal.common.beamlines.beamline_utils import set_beamline as set_utils_beamline +from dodal.devices.i16.dcm import DCM +from dodal.devices.synchrotron import Synchrotron +from dodal.log import set_beamline as set_log_beamline +from dodal.utils import BeamlinePrefix, get_beamline_name + +BL = get_beamline_name("i16") +PREFIX = BeamlinePrefix(BL, suffix="I") +set_log_beamline(BL) +set_utils_beamline(BL) + + +@device_factory() +def synchrotron() -> Synchrotron: + return Synchrotron() + + +# dodal connect should work again after this https://jira.diamond.ac.uk/browse/I16-960 +@device_factory() +def dcm() -> DCM: + return DCM( + temperature_prefix=f"{PREFIX.beamline_prefix}-OP-DCM-01:", + prefix=f"{PREFIX.beamline_prefix}-OP-DCM-01:", + ) diff --git a/src/dodal/devices/i16/dcm.py b/src/dodal/devices/i16/dcm.py new file mode 100644 index 00000000000..031843428f0 --- /dev/null +++ b/src/dodal/devices/i16/dcm.py @@ -0,0 +1,50 @@ +from ophyd_async.epics.core import epics_signal_r, epics_signal_w +from ophyd_async.epics.motor import Motor + +from dodal.devices.common_dcm import BaseDCM, PitchAndRollCrystal, RollCrystal + + +class DCM(BaseDCM[RollCrystal, PitchAndRollCrystal]): + """ + A double crystal monochromator (DCM), used to select the energy of the beam. + + perp describes the gap between the 2 DCM crystals which has to change as you alter + the angle to select the requested energy. + + offset ensures that the beam exits the DCM at the same point, regardless of energy. + """ + + def __init__( + self, + temperature_prefix: str, + prefix: str, + name: str = "", + ) -> None: + with self.add_children_as_readables(): + # Positionable Parameters + self.perp = Motor(prefix + "XTAL2:YPRIME") + self.crystal_1_roll = Motor(prefix + "XTAL1:ROLL") + self.crystal_2_roll = Motor(prefix + "XTAL2:ROLL") + self.crystal_2_pitch = Motor(prefix + "XTAL2:PITCH") + self.crystal_2_fine_pitch_read = epics_signal_r( + float, prefix + "FPMTR:PREAD" + ) + self.crystal_2_fine_pitch_write = epics_signal_w( + float, prefix + "FPMTR:POUT" + ) + self.crystal_2_fine_roll_read = epics_signal_r( + float, prefix + "FRMTR:PREAD" + ) + self.crystal_2_fine_roll_write = epics_signal_w( + float, prefix + "FRMTR:POUT" + ) + + # Temperatures + self.crystal_1_temp1 = epics_signal_r(float, temperature_prefix + "TMP1") + self.crystal_2_temp2 = epics_signal_r(float, temperature_prefix + "TMP2") + self.crystal_1_temp3 = epics_signal_r(float, temperature_prefix + "TMP3") + self.crystal_2_temp4 = epics_signal_r(float, temperature_prefix + "TMP4") + self.crystal_1_temp5 = epics_signal_r(float, temperature_prefix + "TMP5") + self.crystal_2_temp6 = epics_signal_r(float, temperature_prefix + "TMP6") + + super().__init__(prefix, RollCrystal, PitchAndRollCrystal, name)