136 lines
5.5 KiB
Python
136 lines
5.5 KiB
Python
from frappy.core import Readable, Parameter, FloatRange, HasIO, StringIO, Property, IntRange,\
|
|
IDLE, BUSY, WARN, ERROR, Drivable, BoolType, Attached, StructOf
|
|
|
|
|
|
class ACM1219IO(StringIO):
|
|
"""communication with ACM1219"""
|
|
end_of_line = '\n'
|
|
wait_before = 0.05
|
|
identification = [('*IDN?', r'.*')]
|
|
|
|
|
|
class BothChannels(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 1 and 2, and VT',
|
|
StructOf(C1=FloatRange(0, 21.096, unit='pF'), C2=FloatRange(0, 21.096, unit='pF'), VT=FloatRange(-1, 1000, unit='')),
|
|
readonly=True)
|
|
channels_enabled = Parameter('channels on or off', BoolType(), readonly=False)
|
|
_ch_enabled = False
|
|
|
|
def read_value(self):
|
|
# using the inherited HasIO.communicate method to send a command and get the reply
|
|
natempt = 0
|
|
maxAttempts = 5
|
|
|
|
while natempt < maxAttempts:
|
|
try:
|
|
reply = self.communicate(f'readMUC')
|
|
print(reply)
|
|
reply = reply.split(',')
|
|
C1 = float(reply[0])
|
|
C2 = float(reply[1])
|
|
VT = float(reply[2])
|
|
return {'C1': C1, 'C2': C2, 'VT': VT}
|
|
except:
|
|
''
|
|
natempt+=1
|
|
if natempt >= maxAttempts:
|
|
print('Max attempt reached for reading arduino.')
|
|
return self.value
|
|
|
|
def read_status(self):
|
|
# code = self.communicate(f'readStatus') # returns tons of data
|
|
return IDLE, ''
|
|
|
|
def read_channels_enabled(self):
|
|
return self._ch_enabled
|
|
|
|
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._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_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
|
|
|
|
|
|
|