diff --git a/src/dodal/devices/current_amplifiers/femto.py b/src/dodal/devices/current_amplifiers/femto.py index 07e7ec5711..b06a50ad35 100644 --- a/src/dodal/devices/current_amplifiers/femto.py +++ b/src/dodal/devices/current_amplifiers/femto.py @@ -1,3 +1,4 @@ +import asyncio from enum import Enum from bluesky.protocols import Movable, Reading @@ -14,7 +15,7 @@ from dodal.log import LOGGER -class Fmeto100(str, Enum): +class Femto100(str, Enum): sen_1 = "10^4" sen_2 = "10^5" sen_3 = "10^6" @@ -33,8 +34,8 @@ class Fmeto100(str, Enum): class Femto(StandardReadable, Movable): def __init__(self, prefix: str, name: str = "") -> None: with self.add_children_as_readables(HintedSignal): - self.gain = epics_signal_rw(Fmeto100, prefix + "GAIN") - self.current = soft_signal_r_and_setter( + self.gain = epics_signal_rw(Femto100, prefix + "GAIN") + self.current, self._current_set = soft_signal_r_and_setter( float, initial_value=None, units="Amp" ) with self.add_children_as_readables(ConfigSignal): @@ -44,29 +45,35 @@ def __init__(self, prefix: str, name: str = "") -> None: @AsyncStatus.wrap async def set(self, value) -> None: - if self.auto_mode.get_value is True: - LOGGER.info(f"{self.name}-Attempting auto-gain") - await self.auto_gain() - - self._set(value=value, timeout=TIMEOUT) - - @AsyncStatus.wrap - async def _set(self, value, timeout=TIMEOUT) -> None: - self.gain.set(value=value, timeout=timeout) + self.gain.set(value=value, timeout=TIMEOUT) async def read(self) -> dict[str, Reading]: - self.current = await self.analogue_readout.get_value() * float( - await self.gain.get_value() - ) + if await self.auto_mode.get_value() is True: + LOGGER.info(f"{self.name}-Attempting auto-gain") + await self.auto_gain() + gain_value = 10 ** float((await self.gain.get_value()).value.split("^")[1]) + self._current_set(await self.analogue_readout.get_value() / gain_value) return await super().read() async def auto_gain(self) -> bool: + cnt = 0 + success = True + while success and cnt < len(Femto100): + reading = await self.analogue_readout.get_value(cached=False) + if reading > 9.8: + current_gain = int((await self.gain.get_value()).name.split("_")[1]) + current_gain -= 1 + if current_gain < 1: + return False + self.set(value=Femto100[f"sen_{current_gain}"]) + elif reading < 0.8: + current_gain = int((await self.gain.get_value()).name.split("_")[1]) + current_gain += 1 + if current_gain > len(Femto100): + return False + self.set(value=Femto100[f"sen_{current_gain}"]) + else: + return True + await asyncio.sleep(0.5) + cnt += 1 return True - # check if analogure readout is within range - # if so done - # else - # change gain until it is within range - # or - # when it hit the edge of the range - # or - # when it tried the entire range.