further work on needle valve, pump and lakeshore
This commit is contained in:
128
frappy_psi/butterflyvalve.py
Normal file
128
frappy_psi/butterflyvalve.py
Normal file
@@ -0,0 +1,128 @@
|
||||
# *****************************************************************************
|
||||
#
|
||||
# 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:
|
||||
# M. Zolliker <markus.zolliker@psi.ch>
|
||||
#
|
||||
# *****************************************************************************
|
||||
|
||||
from frappy.core import Attached, Command, EnumType, FloatRange, \
|
||||
Drivable, Parameter, BUSY, IDLE, ERROR
|
||||
|
||||
|
||||
class Valve(Drivable):
|
||||
motor = Attached(Drivable) # refers to motor module
|
||||
value = Parameter('valve state',
|
||||
EnumType(closed=0, open=1, undefined=2),
|
||||
default=2)
|
||||
status = Parameter() # inherit properties from Drivable
|
||||
target = Parameter('valve target',
|
||||
EnumType(closed=0, open=1),
|
||||
readonly=False)
|
||||
# TODO: convert to properties after tests
|
||||
open_pos = Parameter('target position for open state', FloatRange(), readonly=False, default=80)
|
||||
mid_pos = Parameter('position for changing speed', FloatRange(), readonly=False, default=5)
|
||||
fast_speed = Parameter('normal speed', FloatRange(), readonly=False, default=40)
|
||||
slow_speed = Parameter('reduced speed', FloatRange(), readonly=False, default=10)
|
||||
__motor_target = None
|
||||
__status = IDLE, ''
|
||||
__value = 'undefined'
|
||||
__drivestate = 0 # 2 when driving to intermediate target or on retry, 1 when driving to final target, 0 when idle
|
||||
|
||||
def doPoll(self):
|
||||
mot = self.motor
|
||||
motpos = mot.read_value()
|
||||
scode, stext = mot.read_status()
|
||||
drivestate = self.__drivestate
|
||||
if scode >= ERROR:
|
||||
if self.__drivestate and self.__remaining_tries > 0:
|
||||
drivestate = 2
|
||||
self.__remaining_tries -= 1
|
||||
mot.reset()
|
||||
mot.write_speed(self.slow_speed)
|
||||
self.__status = BUSY, f'retry {self._action}'
|
||||
else:
|
||||
self.__status = ERROR, f'valve motor: {stext}'
|
||||
elif scode < BUSY:
|
||||
if self.__motor_target is not None and mot.target != self.__motor_target:
|
||||
self.__status = ERROR, 'motor was driven directly'
|
||||
elif drivestate == 2:
|
||||
self.goto(self.target)
|
||||
drivestate = 1
|
||||
else:
|
||||
if -3 < motpos < 3:
|
||||
self.__value = 'closed'
|
||||
self.__status = IDLE, ''
|
||||
elif self.open_pos * 0.5 < motpos < self.open_pos * 1.5:
|
||||
self.__value = 'open'
|
||||
self.__status = IDLE, ''
|
||||
else:
|
||||
self.__status = ERROR, 'undefined'
|
||||
if self.__drivestate and not self.isBusy(self.__status):
|
||||
drivestate = 0
|
||||
self.__motor_target = None
|
||||
self.setFastPoll(False)
|
||||
self.__drivestate = drivestate
|
||||
self.read_status()
|
||||
self.read_value()
|
||||
|
||||
def read_status(self):
|
||||
return self.__status
|
||||
|
||||
def read_value(self):
|
||||
if self.read_status()[0] >= BUSY:
|
||||
return 'undefined'
|
||||
return self.__value
|
||||
|
||||
def goto(self, target):
|
||||
"""go to open, closed or intermediate position
|
||||
|
||||
the intermediate position is targeted when a speed change is needed
|
||||
|
||||
return 2 when a retry is needed, 1 else
|
||||
"""
|
||||
mot = self.motor
|
||||
if target: # 'open'
|
||||
self._action = 'opening'
|
||||
if True or mot.value > self.mid_pos:
|
||||
mot.write_speed(self.fast_speed)
|
||||
self.__motor_target = mot.write_target(self.open_pos)
|
||||
return 1
|
||||
mot.write_speed(self.slow_speed)
|
||||
self.__motor_target = mot.write_target(self.mid_pos)
|
||||
return 2
|
||||
self._action = 'closing'
|
||||
if mot.value > self.mid_pos * 2:
|
||||
mot.write_speed(self.fast_speed)
|
||||
self.__motor_target = mot.write_target(self.mid_pos)
|
||||
return 2
|
||||
mot.write_speed(self.slow_speed)
|
||||
self.__motor_target = mot.write_target(0)
|
||||
return 1
|
||||
|
||||
def write_target(self, target):
|
||||
self.__remaining_tries = 5
|
||||
self.__drivestate = self.goto(target)
|
||||
self.__status = BUSY, self._action
|
||||
self.read_status()
|
||||
self.read_value()
|
||||
self.setFastPoll(True)
|
||||
|
||||
@Command() # python decorator to mark it as a command
|
||||
def stop(self):
|
||||
"""stop the motor -> value might get undefined"""
|
||||
self.__drivestate = 0
|
||||
self.motor.stop()
|
||||
Reference in New Issue
Block a user