diff --git a/cfg/razorbillUC220T_cfg.py b/cfg/razorbillUC220T_cfg.py index e023c2b..ce757fb 100644 --- a/cfg/razorbillUC220T_cfg.py +++ b/cfg/razorbillUC220T_cfg.py @@ -3,13 +3,14 @@ Node('UC220T.psi.ch', 'A Razorbill UC220T controlled by a RP100 high voltage powersupply and a ACM1219 (AD7746) capacitance meter', - interface='tcp://5123') + interface='tcp://3000') Mod('io1', 'frappy_psi.RP100.RP100IO', 'communication', - uri='serial:///dev/ttyACM0?baudrate=9600+bytesize=8+parity=none+stopbits=1') -Mod('V1', + uri='serial:///dev/ttyACM1?baudrate=9600+bytesize=8+parity=none+stopbits=1', + visibility=2) +Mod('Tension', 'frappy_psi.RP100.VoltageChannel', 'Voltage Channel 1', temp='T', @@ -17,9 +18,9 @@ Mod('V1', target=Param(min=-200, max=200), max_target=120, min_target=-20, - slew_rate=100, + slew_rate=5, channel=1) -Mod('V2', +Mod('Compression', 'frappy_psi.RP100.VoltageChannel', 'Voltage Channel 2', temp='T', @@ -27,58 +28,112 @@ Mod('V2', target=Param(min=-200, max=200), max_target=120, min_target=-20, - slew_rate=100, + slew_rate=5, channel=2) Mod('io2', 'frappy_psi.ACM1219.ACM1219IO', 'communication', - uri='serial:///dev/ttyUSB0?baudrate=9600+bytesize=8+parity=none+stopbits=1') -Mod('C1C2', - 'frappy_psi.ACM1219.BothChannels', - 'Capacitance channels 1 and 2', - io='io2') -Mod('d', - 'frappy_psi.ACM1219.Displacement', - 'razorbill displacement from capacitance', - cap='C1C2', + uri='serial:///dev/ttyUSB1?baudrate=9600+bytesize=8+parity=none+stopbits=1', + visibility=2) +Mod('C1', + 'frappy_psi.ACM1219.OneChannel', + 'channel 1', + channel_enabled=True, channel=1, + io='io2', + group='cap') + +Mod('io3', + 'frappy_psi.ACM1219.ACM1219IO', + 'communication', + uri='serial:///dev/ttyUSB2?baudrate=9600+bytesize=8+parity=none+stopbits=1', + visibility=2) +Mod('C2', + 'frappy_psi.ACM1219.OneChannel', + 'channel 1', + channel_enabled=True, + channel=1, + io='io3', + group='cap') + +# Mod('C1', +# 'frappy_psi.ACM1219.Channel', +# 'channel 1', +# group='cap') +# Mod('C2', +# 'frappy_psi.ACM1219.Channel', +# 'channel 2', +# group='cap') +# Mod('C1C2', +# 'frappy_psi.ACM1219.BothChannels', +# 'Capacitance channels 1 and 2', +# chan1='C1', +# chan2='C2', +# channels_enabled=True, +# io='io2', +# group='cap') +Mod('d', + 'frappy_psi.razorbill.Displacement', + 'razorbill displacement from capacitance', + cap='C1', alpha290K=56.710, d0=95.443, Cp=0.01883, d0_curve={'a':4.21,'b':-0.00157,'c':-3.38e-5,'d':5.28e-8,'e':-6.93e-11}, temp='T') +Mod('strain', + 'frappy_psi.razorbill.Strain', + 'Sample strain from force', + displacement='d', + L=3, + ) Mod('F', - 'frappy_psi.ACM1219.Force', + 'frappy_psi.razorbill.Force', 'razorbill force from capacitance', - cap='C1C2', - channel=2, + cap='C2', alpha290K=374.23, f0=315.63, Cp=0.0755, f0_curve={'a':38.9,'b':-0.0147,'c':-0.000346,'d':8.96e-7,'e':-1.58e-9}, temp='T') Mod('stress', - 'frappy_psi.ACM1219.Stress', + 'frappy_psi.razorbill.Stress', 'Sample stress from force', force='F', area=0.1, ) -Mod('strain', - 'frappy_psi.ACM1219.Strain', - 'Sample strain from force', - displacement='d', - L=3, - ) Mod('YM', - 'frappy_psi.ACM1219.YoungsModulus', + 'frappy_psi.razorbill.YoungsModulus', 'Sample youngs modulus from stress and strain', stress='stress', strain='strain', ) Mod('T', - 'frappy_psi.dummy.Temp', + 'frappy_psi.razorbill.Temp', 'dummy T written from client', - target=Param(min=1, max=325), + target=Param(value=300, min=1, max=325), ) + + +Mod('io4', + 'frappy_psi.ls372.StringIO', + 'the communication device', + uri='tcp://192.168.3.3:7777', + visibility=2 +) +Mod('lsswitcher', + 'frappy_psi.ls372.Switcher', + 'Switcher control of Lsc controller', + uri='tcp://192.168.3.3:7777', + io='io4', +) +Mod('res', + 'frappy_psi.ls372.ResChannel', + 'resistivity', + iexc='100uA', + range='63.2mOhm', + channel=1, + switcher='lsswitcher', +) diff --git a/frappy_psi/ACM1219.py b/frappy_psi/ACM1219.py index fee5cde..d1bc27f 100644 --- a/frappy_psi/ACM1219.py +++ b/frappy_psi/ACM1219.py @@ -39,11 +39,54 @@ class ACM1219IO(StringIO): super().checkHWIdent() +class Channel(Readable): + value = Parameter('one channel', unit='pF') + + +class OneChannel(HasIO, Readable): + """read both capacitance channels in multiplex mode""" + + # define the communication class for automatic creation of the IO module + ioClass = ACM1219IO + + # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) + value = Parameter('Capacitance of one channel', + FloatRange(0, 21.096, unit='pF'), readonly=True) + channel_enabled = Parameter('channel on or off', BoolType(), readonly=False) + channel = Property('the voltage channel', datatype=IntRange(1,2)) + _ch_enabled = False + + def read_value(self): + reply = self.communicate('readCVT').split(',') + value = float(reply[self.channel-1]) + return value + + def read_status(self): + # code = self.communicate(f'readStatus') # returns tons of data + return IDLE, '' + + def read_channel_enabled(self): + return self._ch_enabled + + def write_channel_enabled(self, channel_enabled): + if channel_enabled: + self.communicate(f'setCIN {self.channel},0,00.0,00.0,0,00.0,00.0') + # self.communicate(f'setCIN 2,0,00.0,00.0,0,00.0,00.0') + self._ch_enabled = True + else: + self.communicate(f'setCIN 0,0,00.0,00.0,0,00.0,00.0') + self._ch_enabled = False + + return self.read_channel_enabled() + + class BothChannels(HasIO, Readable): """read both capacitance channels in multiplex mode""" # define the communication class for automatic creation of the IO module ioClass = ACM1219IO + chan1 = Attached(Readable) + chan2 = Attached(Readable) # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) value = Parameter('Capacitance 1 and 2, and VT', @@ -51,8 +94,9 @@ class BothChannels(HasIO, Readable): readonly=True) channels_enabled = Parameter('channels on or off', BoolType(), readonly=False) _ch_enabled = False + _channel = 1 - def read_value(self): + def Xread_value(self): # using the inherited HasIO.communicate method to send a command and get the reply natempt = 0 maxAttempts = 5 @@ -65,6 +109,8 @@ class BothChannels(HasIO, Readable): C1 = float(reply[0]) C2 = float(reply[1]) VT = float(reply[2]) + self.chan1.value = C1 + self.chan2.value = C2 return {'C1': C1, 'C2': C2, 'VT': VT} except: '' @@ -73,6 +119,16 @@ class BothChannels(HasIO, Readable): print('Max attempt reached for reading arduino.') return self.value + def read_value(self): + reply = self.communicate('readCVT').split(',') + value = float(reply[self._channel-1]) + previous = dict(self.value) + previous[f'C{self._channel}'] = value + getattr(self, f'chan{self._channel}').value = value + self._channel = 3 - self._channel + self.communicate(f'setCIN {self._channel},0,00.0,00.0,0,00.0,00.0') + return previous + def read_status(self): # code = self.communicate(f'readStatus') # returns tons of data return IDLE, '' @@ -82,122 +138,15 @@ class BothChannels(HasIO, Readable): def write_channels_enabled(self, channels_enabled): if channels_enabled: - self.communicate(f'setCIN 1,0,00.0,00.0,0,00.0,00.0') - self.communicate(f'setCIN 2,0,00.0,00.0,0,00.0,00.0') + self.communicate(f'setCIN {self._channel},0,00.0,00.0,0,00.0,00.0') + # self.communicate(f'setCIN 2,0,00.0,00.0,0,00.0,00.0') self._ch_enabled = True + self.communicate(f'setEXC 2,2,3,1') else: self.communicate(f'setCIN 0,0,00.0,00.0,0,00.0,00.0') self._ch_enabled = False + self.communicate(f'setEXC 0,0,3,1') return self.read_channels_enabled() -class Displacement(Readable): - - # attached classes for capacitance and temperature - cap = Attached() - temp = Attached() - - # internal property to configure the channel - channel = Property('the voltage channel for displacement capacitor', datatype=IntRange(1,2)) - - # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) - value = Parameter('displacement', FloatRange(None, None, unit='um'), readonly=True) - alpha290K = Parameter('capacitor constant at 290 K', FloatRange(None, None, unit='um pF'), readonly=False) - d0 = Parameter('offset displacement', FloatRange(None, None, unit='um'), readonly=False) - Cp = Parameter('parallel capacitance', FloatRange(None, None, unit='pF'), readonly=False) - d0_curve = Parameter('calibration curve for offset displacement', - StructOf(a=FloatRange(None, None, unit='um'), - b=FloatRange(None, None, unit='um/K'), - c=FloatRange(None, None, unit='um/K^2'), - d=FloatRange(None, None, unit='um/K^3'), - e=FloatRange(None, None, unit='um/K^4'),), - readonly=False) - - def read_value(self): - # get temperature and capacitance - temp = self.temp.target - cap = self.cap.value[f'C{self.channel}'] - - # calculate displacement from temperature and capacitance - d0_T = self.d0_curve['a'] + self.d0_curve['b']*temp + self.d0_curve['c']*temp**2 + self.d0_curve['d']*temp**3 + self.d0_curve['e']*temp**4 - - disp = self.alpha290K / (cap - self.Cp) - self.d0 - d0_T - - return disp - - -class Force(Readable): - - # attached classes for capacitance and temperature - cap = Attached() - temp = Attached() - - # internal property to configure the channel - channel = Property('the voltage channel for force capacitor', datatype=IntRange(1,2)) - - # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) - value = Parameter('force', FloatRange(None, None, unit='N'), readonly=True) - alpha290K = Parameter('capacitor constant at 290 K', FloatRange(None, None, unit='N pF'), readonly=False) - f0 = Parameter('offset force', FloatRange(None, None, unit='N'), readonly=False) - Cp = Parameter('parallel capacitance', FloatRange(None, None, unit='pF'), readonly=False) - f0_curve = Parameter('calibration curve for offset force', - StructOf(a=FloatRange(None, None, unit='N'), - b=FloatRange(None, None, unit='N/K'), - c=FloatRange(None, None, unit='N/K^2'), - d=FloatRange(None, None, unit='N/K^3'), - e=FloatRange(None, None, unit='N/K^4'),), - readonly=False) - - def read_value(self): - # get temperature and capacitance - temp = self.temp.target - cap = self.cap.value[f'C{self.channel}'] - - # calculate force from temperature and capacitance - alpha = self.alpha290K * (0.91 + 5e-5*temp + 9e-7*temp**2) - f0_T = self.f0_curve['a'] + self.f0_curve['b']*temp + self.f0_curve['c']*temp**2 + self.f0_curve['d']*temp**3 + self.f0_curve['e']*temp**4 - - force = alpha / (cap - self.Cp) - self.f0 - f0_T - - return force - - -class Stress(Readable): - - # attached classes for displacement - force = Attached() - - # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) - value = Parameter('stress', FloatRange(None, None, unit='GPa'), readonly=True) - area = Parameter('cross sectional area of sample in mm^2', FloatRange(None, None, unit='mm^2'), readonly=False) - - def read_value(self): - return self.force.value / self.area / 1000 - - -class Strain(Readable): - - # attached classes for displacement - displacement = Attached() - - # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) - value = Parameter('strain', FloatRange(None, None, unit='m/m'), readonly=True) - L = Parameter('length of sample in mm', FloatRange(None, None, unit='mm'), readonly=False) - - def read_value(self): - return self.displacement.value / (1000*self.L) - - -class YoungsModulus(Readable): - - # attached classes for displacement - stress = Attached() - strain = Attached() - - # modifying a property of inherited parameters (unit is propagated to the FloatRange datatype) - value = Parameter('Young\'s modulus', FloatRange(None, None, unit='GPa'), readonly=True) - - def read_value(self): - return self.stress.value / self.strain.value - diff --git a/frappy_psi/RP100.py b/frappy_psi/RP100.py index 87e5974..0aa8a9f 100644 --- a/frappy_psi/RP100.py +++ b/frappy_psi/RP100.py @@ -115,11 +115,13 @@ class VoltageChannel(HasIO, Drivable): return self.read_slew_rate() def read_output_state(self): - return bool(self.communicate(f'OUTP{self.channel}?')) + return int(self.communicate(f'OUTP{self.channel}?')) def write_output_state(self, output_state): self.communicate(f'OUTP{self.channel} {int(output_state)};*OPC?') - return self.read_slew_rate() + if not output_state: + self.write_target(0) + return self.read_output_state() def read_meas_voltage(self): return float(self.communicate(f'MEAS{self.channel}:VOLT?')) diff --git a/frappy_psi/dummy.py b/frappy_psi/dummy.py deleted file mode 100644 index b73f881..0000000 --- a/frappy_psi/dummy.py +++ /dev/null @@ -1,34 +0,0 @@ -# ***************************************************************************** -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Module authors: -# Paul M. Neves -# ***************************************************************************** - -from frappy.core import Readable, Parameter, FloatRange, HasIO, StringIO, Property, IntRange,\ - IDLE, BUSY, WARN, ERROR, Drivable, BoolType, Attached, Writable - - -class Temp(Writable): - """a voltage output with loop""" - - target = Parameter('target voltage', FloatRange(0, 325, unit='K'), - readonly=False) - - def write_target(self, target): - self.value = target - - def read_value(self): - return 0 \ No newline at end of file