frappy/frappy_psi/ah2700.py
Markus Zolliker 0d265b9752 make return value 'Done' unneccessary
'Done' was introduced in order to suppress unneccessary
duplicate updates. However, since super calls on access methods are
allowed, it is not nice when such a method returns Done, as this
is not automagically replaced by the current parameter value.
As a consequence:

- using Done is discouraged, but not (yet) removed in all code
- the 'omit_unchanged_within' property is moved from Module to an
  internal Parameter property 'update_unchanged'
- its default is moved from a SEC node property to generalConfig
- the 'update_unchanged' parameter property may be set to
  'never' for parameters where duplicate updates make no sense
- this property might be set to 'always', for measurements, where
  even unchanged values taken from HW should be transmitted

Change-Id: I2847c983ca09c2c4098e402edd08d0c96c3913f4
Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/30672
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
2023-04-21 16:17:30 +02:00

93 lines
3.4 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# *****************************************************************************
# 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:
# Markus Zolliker <markus.zolliker@psi.ch>
# *****************************************************************************
"""Andeen Hagerling capacitance bridge"""
from frappy.core import FloatRange, HasIO, Parameter, Readable, StringIO, nopoll
class Ah2700IO(StringIO):
end_of_line = '\r\n'
timeout = 5
class Capacitance(HasIO, Readable):
value = Parameter('capacitance', FloatRange(unit='pF'))
freq = Parameter('frequency', FloatRange(unit='Hz'), readonly=False, default=0)
voltage = Parameter('voltage', FloatRange(unit='V'), readonly=False, default=0)
loss = Parameter('loss', FloatRange(unit='deg'), default=0)
ioClass = Ah2700IO
def parse_reply(self, reply):
if reply.startswith('SI'): # this is an echo
self.communicate('SERIAL ECHO OFF')
reply = self.communicate('SI')
if not reply.startswith('F='): # this is probably an error message like "LOSS TOO HIGH"
self.status = [self.Status.ERROR, reply]
return self.value
self.status = [self.Status.IDLE, '']
# examples of replies:
# 'F= 1000.0 HZ C= 0.000001 PF L> 0.0 DS V= 15.0 V'
# 'F= 1000.0 HZ C= 0.0000059 PF L=-0.4 DS V= 15.0 V OVEN'
# 'LOSS TOO HIGH'
# make sure there is always a space after '=' and '>'
# split() ignores multiple white space
reply = reply.replace('=', '= ').replace('>', '> ').split()
_, freq, _, _, cap, _, _, loss, lossunit, _, volt = reply[:11]
self.freq = freq
self.voltage = volt
if lossunit == 'DS':
self.loss = loss
else: # the unit was wrong, we want DS = tan(delta), not NS = nanoSiemens
reply = self.communicate('UN DS').split() # UN DS returns a reply similar to SI
try:
self.loss = reply[7]
except IndexError:
pass # don't worry, loss will be updated next time
return cap
def read_value(self):
return self.parse_reply(self.communicate('SI')) # SI = single trigger
@nopoll
def read_freq(self):
self.read_value()
return self.freq
@nopoll
def read_loss(self):
self.read_value()
return self.loss
@nopoll
def read_voltage(self):
self.read_value()
return self.voltage
def write_freq(self, value):
self.value = self.parse_reply(self.communicate('FR %g;SI' % value))
return self.freq
def write_voltage(self, value):
self.value = self.parse_reply(self.communicate('V %g;SI' % value))
return self.voltage