# ***************************************************************************** # 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, StructOf class Temp(Writable): """stores sample temperature""" target = Parameter('target voltage', FloatRange(0, 325, unit='K'), readonly=False) def write_target(self, target): self.value = target def read_value(self): return self.value class Displacement(Readable): # attached classes for capacitance and temperature cap = Attached() temp = Attached() # 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 # 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() # 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 # 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): if self.strain.value: return self.stress.value / self.strain.value else: return 0