nf8753.py 4.55 KB
Newer Older
1
2
3
4
5
"""
Bliss controller for ethernet NewFocus 87xx series piezo controller.
A. Beteva, M. Guijarro, ESRF BCU
"""
import time
blissadm@id30_massif3's avatar
blissadm@id30_massif3 committed
6
from warnings import warn
7
8

from bliss.controllers.motor import Controller; from bliss.common import log
9
from bliss.common.axis import AxisState
10
from bliss.comm.util import get_comm, TCP
11
12
13
from bliss.common import event
import gevent.lock

cyril@lid269's avatar
pep8    
cyril@lid269 committed
14
DELAY = 0.02  # delay between 2 commands
15

16
17
18

class NF8753(Controller):

19
20
    def __init__(self, *args, **kwargs):
        Controller.__init__(self, *args, **kwargs)
21

22
        self.__current_selected_channel = None
23
24
25
26
        self.lock = gevent.lock.RLock()
        self.__busy = False

    def initialize(self):
27
28
29
30
31
32
33
34
        try:
            self.sock = get_comm(self.config.config_dict, TCP, port=23)
        except ValueError:
            host = self.config.get("host")
            warn("'host' keyword is deprecated. Use 'tcp' instead", DeprecationWarning)
            comm_cfg = {'tcp': {'url': host } }
            self.sock = get_comm(comm_cfg, port=23)

35
        if '=2' in self._write_read(None, "DRT", raw=True):
36
37
            raise RuntimeError("Uncompatible closed-loop driver detected in daisy chain")

38
39
40
41
42
    def finalize(self):
        self.sock.close()
        # this controller can't reconnect immediately
        # after socket is disconnected, so we put a delay here to make sure
        # socket is really closed on the controller side
cyril@lid269's avatar
pep8    
cyril@lid269 committed
43
        time.sleep(5 * DELAY)
44
45
46
47

    def initialize_axis(self, axis):
        axis.driver = axis.config.get("driver", str)
        axis.channel = axis.config.get("channel", int)
48
        axis.accumulator = None
49

50
51
        event.connect(axis, "move_done", self._axis_move_done)

cyril@lid269's avatar
pep8    
cyril@lid269 committed
52
        # self._write_no_reply(axis, "JOF") #, raw=True)
53
        self._write_no_reply(axis, "MON %s" % axis.driver)
54
55
56

    def _select_channel(self, axis):
        change_channel = "CHL %s=%d" % (axis.driver, axis.channel)
57
58
        if change_channel != self.__current_selected_channel:
            self.__current_selected_channel = change_channel
59
            self._write_no_reply(None, change_channel)
60
61
62

    def _write_no_reply(self, axis, cmd_string):
        with self.lock:
63
64
            if not cmd_string.endswith('\r\n'):
                cmd_string += '\r\n'
65
66
            if axis is not None:
                self._select_channel(axis)
cyril@lid269's avatar
pep8    
cyril@lid269 committed
67
            # print 'sending', cmd_string
68
69
            self.sock.write_readline(cmd_string, eol='>')
            time.sleep(DELAY)
70

71
    def _write_read(self, axis, cmd_string, eol='\r\n>', raw=False):
72
        with self.lock:
73
74
75
76
77
78
            if not cmd_string.endswith('\r\n'):
                cmd_string += '\r\n'

            if axis is not None:
                self._select_channel(axis)

cyril@lid269's avatar
pep8    
cyril@lid269 committed
79
            # print 'sending', cmd_string, 'waiting for reply...'
80
81
            ans = self.sock.write_readline(cmd_string, eol=eol)
            time.sleep(DELAY)
cyril@lid269's avatar
pep8    
cyril@lid269 committed
82
            # print 'reply=', ans
83
84
85
86
87

            ans = ans.replace(">", "")
            if raw:
                return ans
            else:
88
                return ans.split("=")[1].split("\r\n>")[0]
89

90
91
    def read_velocity(self, axis):
        return int(self._write_read(axis, "VEL %s %d" % (axis.driver, axis.channel)))
92

93
    def set_velocity(self, axis, new_velocity):
cyril@lid269's avatar
pep8    
cyril@lid269 committed
94
        # self._write_no_reply(axis, "VEL %s %s=%d" % (axis.driver, axis.channel, new_velocity))
95
96
97
98
99
        return self.read_velocity(axis)

    def state(self, axis):
        sta = self._write_read(axis, "STA", eol='\r\n>', raw=True)
        for line in sta.split("\n"):
100
101
102
            if line.startswith(axis.driver):
                status_byte = int(line.split("=")[-1], 16)
                if status_byte & 0x0000001:
103
                    return AxisState("MOVING")
104
                else:
105
                    return AxisState("READY")
106
107
108
109
110
111

    def is_busy(self):
        return self.__busy

    def prepare_move(self, motion):
        self.__busy = True
112
113
        self.__moving_axis = motion.axis
        if self.__moving_axis.accumulator is None:
cyril@lid269's avatar
pep8    
cyril@lid269 committed
114
115
            _accu = self.__moving_axis.settings.get("offset") * self.__moving_axis.steps_per_unit
            self.__moving_axis.accumulator = _accu
116
        self.__moving_axis.accumulator += motion.delta
117
118
119

    def _axis_move_done(self, done):
        if done:
cyril@lid269's avatar
pep8    
cyril@lid269 committed
120
121
122
123
            # print ">"*10, "AXIS MOVE DONE"
            self.__busy = False
            self.__moving_axis.position(self.__moving_axis.accumulator / self.__moving_axis.steps_per_unit)

124
    def start_one(self, motion):
cyril@lid269's avatar
pep8    
cyril@lid269 committed
125
        # print "in motion start_one for axis", motion.axis.name
126
        self._write_no_reply(motion.axis, "REL %s=%d G" % (motion.axis.driver, motion.delta))
127
128

    def stop(self, axis):
129
        self._write_no_reply(axis, "HAL")