From dc81de9adcfb8221d18f856a0ca0a2d62ffa6f8b Mon Sep 17 00:00:00 2001 From: AntonioT7 Date: Mon, 13 Feb 2023 10:29:03 +0100 Subject: [PATCH 01/21] Improvement on steering the valve in bronkhorst_ELflow --- basil/HL/bronkhorst_elflow.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index d0439c8f8..1cbc50d1c 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -52,6 +52,10 @@ def read(self): return ret def set_setpoint(self, value): + + if not isinstance(value, int): + raise ValueError(f"Given value has to be of type integer, is {type(value)}!") + cmd = [1, 1, 0x21, (value >> 8) & 0xFF, value & 0xFF] self.write(cmd) ret = self.read() From a7ac68359aac5d4cddb5f7c8408d4843a189f8e0 Mon Sep 17 00:00:00 2001 From: AntonioT7 Date: Wed, 30 Nov 2022 14:44:40 +0100 Subject: [PATCH 02/21] parent df1180ba5c40dd45a9ea336bba19e1c4e8c0375c author AntonioT7 1669815880 +0100 committer Matthias 1715085603 +0200 new julabo fp50 new julabo fp50 Update julabo_FP50.yaml new julabo fp50 --- basil/HL/julabo_FP50.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 basil/HL/julabo_FP50.yaml diff --git a/basil/HL/julabo_FP50.yaml b/basil/HL/julabo_FP50.yaml new file mode 100644 index 000000000..62531bab3 --- /dev/null +++ b/basil/HL/julabo_FP50.yaml @@ -0,0 +1,13 @@ +""" +Device description for using the julabo FP50 chiller +set_ function expect a parameter, get_ function return a parameter. +""" + +get_temp: in_sp_00 # get current set temperature +set_temp: out_sp_00 # set the temperature +get_curr_temp: in_pv_00 # get the current bath temperature +get_version: version # get the version of the device +get_status: status # see its status (manual start, remote control, ...) +set_power: out_hil_00 # Set the desired maximum cooling power (0% to 100%). Note: Enter the value with a preceding negative sign! This setting is meaningful only for FP cooling machines. +on: out_mode_05 1 # start (parameter 1) +off: out_mode_05 0 # stop (parameter 0) From 5a4b139075ebd65977cccdc365a26094f0504e53 Mon Sep 17 00:00:00 2001 From: Thomas Senger Date: Wed, 7 Dec 2022 11:01:52 +0100 Subject: [PATCH 03/21] Julabo FP50: update julabo FP50: update --- basil/HL/julabo_FP50.yaml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 basil/HL/julabo_FP50.yaml diff --git a/basil/HL/julabo_FP50.yaml b/basil/HL/julabo_FP50.yaml deleted file mode 100644 index 62531bab3..000000000 --- a/basil/HL/julabo_FP50.yaml +++ /dev/null @@ -1,13 +0,0 @@ -""" -Device description for using the julabo FP50 chiller -set_ function expect a parameter, get_ function return a parameter. -""" - -get_temp: in_sp_00 # get current set temperature -set_temp: out_sp_00 # set the temperature -get_curr_temp: in_pv_00 # get the current bath temperature -get_version: version # get the version of the device -get_status: status # see its status (manual start, remote control, ...) -set_power: out_hil_00 # Set the desired maximum cooling power (0% to 100%). Note: Enter the value with a preceding negative sign! This setting is meaningful only for FP cooling machines. -on: out_mode_05 1 # start (parameter 1) -off: out_mode_05 0 # stop (parameter 0) From a30cfbfaea05e9ef37ef5d03d98dddd9ef47580f Mon Sep 17 00:00:00 2001 From: Thomas Senger Date: Tue, 28 Feb 2023 13:36:23 +0100 Subject: [PATCH 04/21] WIP: improve bronkhorst flowmeter implementation --- basil/HL/bronkhorst_elflow.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 1cbc50d1c..bb42cec1d 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -18,6 +18,13 @@ class Bronkhorst_ELFLOW(HardwareLayer): ''' Bronkhorst ELFLOW ''' + CMDS = { + 'get_valve_opening': '06800472417241\r\n', # These bytes will make the flow meter send back the opening + 'measure_flow': 'b":06800401210120\r\n"', # These bytes will measure the gas flow through the valve in % + 'read_max_capacity': '068004014D014D\r\n' # These bytes will read the maximum capacity of the current flow + } + + def __init__(self, intf, conf): self.debug = 0 self.node = "80" @@ -51,6 +58,23 @@ def read(self): ret.append(int(ret_s[5 + 2 * i:5 + 2 * (i + 1)], 16)) return ret + + def get_opening(self): + self._intf.write(self.CMDS['get_valve_opening']) + + def get_flow(self): + self._intf.write(self.CMDS['measure_flow']) + self._intf.readline().decode() + reading = self._intf.readline().decode()[11:-2] + print(reading) + int_flow = int(reading, 16) + print(int_flow) + + + + def get_max_cap(self): + self._intf.write(self.CMDS['read_max_capacity']) + def set_setpoint(self, value): if not isinstance(value, int): @@ -70,6 +94,7 @@ def set_setpoint(self, value): def get_setpoint(self): cmd = [4, 1, 0x21, 1, 0x21] + # 06800401210121\r\n self.write(cmd) ret = self.read() if len(ret) != 5: @@ -88,6 +113,7 @@ def set_control_mode(self, value): 8 valve fully open 20 valve steering (valve=setpoint)""" cmd = [1, 1, 4, value & 0xFF] + # 0580010104xx\r\n where xx self.write(cmd) ret = self.read() if len(ret) != 3: @@ -167,6 +193,7 @@ def get_controller_speed(self): def get_measure(self): cmd = [4, 1, 0x21, 1, 0x20] + # 06800401210120\r\n self.write(cmd) ret = self.read() if len(ret) != 5: @@ -177,3 +204,10 @@ def get_measure(self): else: logger.debug("ELFLOW.get_valve_output() ret error ret=%s" % str(ret)) return -1 + + def get_max_capacity(self): + cmd = [4, 1, 0x4D, 1, 0x4D] + # 068004014D014D\r\n + self.write(cmd) + ret = self.read() + print(ret) From ef13821f591aa92534cf5b4417cf8d4323c22678 Mon Sep 17 00:00:00 2001 From: Thomas Senger Date: Tue, 28 Feb 2023 13:53:44 +0100 Subject: [PATCH 05/21] WIP: add a link to the commads document --- basil/HL/bronkhorst_elflow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index bb42cec1d..17cbbf5a6 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -16,6 +16,7 @@ class Bronkhorst_ELFLOW(HardwareLayer): ''' Bronkhorst ELFLOW + Manual can be found here https://www.bronkhorst.com/getmedia/77a1438f-e547-4a79-95ad-53e81fd38a97/917027-Manual-RS232-interface.pdf ''' CMDS = { From 0bb32366d2d3b9905ca3764e7d4228ac38b9da7b Mon Sep 17 00:00:00 2001 From: Thomas Senger Date: Wed, 8 Mar 2023 14:40:09 +0100 Subject: [PATCH 06/21] WIP: adding commands --- basil/HL/bronkhorst_elflow.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 17cbbf5a6..069496b7a 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -20,9 +20,10 @@ class Bronkhorst_ELFLOW(HardwareLayer): ''' CMDS = { - 'get_valve_opening': '06800472417241\r\n', # These bytes will make the flow meter send back the opening - 'measure_flow': 'b":06800401210120\r\n"', # These bytes will measure the gas flow through the valve in % - 'read_max_capacity': '068004014D014D\r\n' # These bytes will read the maximum capacity of the current flow + 'get_valve_opening': ':06800472417241\r\n', # These bytes will make the flow meter send back the opening + 'measure_flow': ':06800401210120\r\n', # These bytes will measure the gas flow through the valve in % + 'read_max_capacity': ':068004014D014D\r\n', # These bytes will read the maximum capacity of the current flow + 'read_control_mode': ':06800401040104\r\n' # these bytes will give what control mode is on } @@ -116,7 +117,9 @@ def set_control_mode(self, value): cmd = [1, 1, 4, value & 0xFF] # 0580010104xx\r\n where xx self.write(cmd) + print(cmd) ret = self.read() + print(ret) if len(ret) != 3: logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) return -1 @@ -128,6 +131,7 @@ def set_control_mode(self, value): def get_control_mode(self): cmd = [4, 1, 1, 1, 4] + # :06800401040104\r\n self.write(cmd) ret = self.read() if len(ret) != 4: From a42bfcd322c8b7d559cea396e29a22c5d8065e71 Mon Sep 17 00:00:00 2001 From: Thomas Senger Date: Fri, 10 Mar 2023 11:36:07 +0100 Subject: [PATCH 07/21] WIP: delete the functions of get/set control mode written by thirono --- basil/HL/bronkhorst_elflow.py | 41 ++++------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 069496b7a..5d43b2a6a 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -6,6 +6,7 @@ # import logging +import time import struct from basil.HL.RegisterHardwareLayer import HardwareLayer @@ -21,9 +22,10 @@ class Bronkhorst_ELFLOW(HardwareLayer): CMDS = { 'get_valve_opening': ':06800472417241\r\n', # These bytes will make the flow meter send back the opening - 'measure_flow': ':06800401210120\r\n', # These bytes will measure the gas flow through the valve in % + 'measure_flow': ':06800401210120\r\n', # These bytes will measure the gas flow through the valve in % 'read_max_capacity': ':068004014D014D\r\n', # These bytes will read the maximum capacity of the current flow - 'read_control_mode': ':06800401040104\r\n' # these bytes will give what control mode is on + 'read_control_mode': ':06800401040104', # these bytes will give what control mode is on + 'set_control_mode': ':0580010104', } @@ -108,41 +110,6 @@ def get_setpoint(self): logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) return -1 - def set_control_mode(self, value): - """ 0 setpoint source RS232 - 3 valve close - 4 freeze valuve out - 8 valve fully open - 20 valve steering (valve=setpoint)""" - cmd = [1, 1, 4, value & 0xFF] - # 0580010104xx\r\n where xx - self.write(cmd) - print(cmd) - ret = self.read() - print(ret) - if len(ret) != 3: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 0 and ret[1] == 0 and ret[2] == 4: - return 0 - else: - logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) - return -1 - - def get_control_mode(self): - cmd = [4, 1, 1, 1, 4] - # :06800401040104\r\n - self.write(cmd) - ret = self.read() - if len(ret) != 4: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 2 and ret[1] == cmd[1] and ret[2] == cmd[2]: - return ret[3] - else: - logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) - return -1 - def set_valve_output(self, value): cmd = [1, 114, 0x41, (value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF] self.write(cmd) From 1df7aaef2e1cc5b54dc5a2c94e92ce7baa9cd433 Mon Sep 17 00:00:00 2001 From: Thomas Senger Date: Fri, 10 Mar 2023 19:03:54 +0100 Subject: [PATCH 08/21] WIP: bring back the functions from thirono for a while --- basil/HL/bronkhorst_elflow.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 5d43b2a6a..d4960ac09 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -110,6 +110,37 @@ def get_setpoint(self): logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) return -1 + def set_control_mode(self, value): + """ 0 setpoint source RS232 + 3 valve close + 4 freeze valuve out + 8 valve fully open + 20 valve steering (valve=setpoint)""" + cmd = [1, 1, 4, value & 0xFF] + self.write(cmd) + ret = self.read() + if len(ret) != 3: + logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) + return -1 + elif ret[0] == 0 and ret[1] == 0 and ret[2] == 4: + return 0 + else: + logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) + return -1 + + def get_control_mode(self): + cmd = [4, 1, 1, 1, 4] + self.write(cmd) + ret = self.read() + if len(ret) != 4: + logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) + return -1 + elif ret[0] == 2 and ret[1] == cmd[1] and ret[2] == cmd[2]: + return ret[3] + else: + logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) + return -1 + def set_valve_output(self, value): cmd = [1, 114, 0x41, (value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF] self.write(cmd) From 14db023b14ab21d4c4caa54c1ec5bfec9bfe482d Mon Sep 17 00:00:00 2001 From: AntonioT7 Date: Mon, 13 Mar 2023 14:04:35 +0100 Subject: [PATCH 09/21] brokhorst valve control and measure N2 flow is ready --- basil/HL/bronkhorst_elflow.py | 224 +++++++++------------------------- 1 file changed, 59 insertions(+), 165 deletions(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index d4960ac09..4e5aac6db 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -6,8 +6,8 @@ # import logging -import time import struct +import time from basil.HL.RegisterHardwareLayer import HardwareLayer @@ -17,200 +17,94 @@ class Bronkhorst_ELFLOW(HardwareLayer): ''' Bronkhorst ELFLOW - Manual can be found here https://www.bronkhorst.com/getmedia/77a1438f-e547-4a79-95ad-53e81fd38a97/917027-Manual-RS232-interface.pdf + Manual can be found here: + https://www.bronkhorst.com/getmedia/77a1438f-e547-4a79-95ad-53e81fd38a97/917027-Manual-RS232-interface.pdf ''' CMDS = { - 'get_valve_opening': ':06800472417241\r\n', # These bytes will make the flow meter send back the opening - 'measure_flow': ':06800401210120\r\n', # These bytes will measure the gas flow through the valve in % - 'read_max_capacity': ':068004014D014D\r\n', # These bytes will read the maximum capacity of the current flow - 'read_control_mode': ':06800401040104', # these bytes will give what control mode is on + 'get_measure_flow': ':06800401210120', + 'get_capacity': ':068004014D014D', + 'get_control_mode': ':06800401040104', 'set_control_mode': ':0580010104', + 'set_setpoint': ':0680010121', + 'get_setpoint': ':06800401210121', } - def __init__(self, intf, conf): self.debug = 0 self.node = "80" super(Bronkhorst_ELFLOW, self).__init__(intf, conf) + self.pre_time = time.time() def init(self): super(Bronkhorst_ELFLOW, self).init() def write(self, cmd): - cmd_s = "" - for c in cmd: - cmd_s = cmd_s + "%02X" % c - cmd_s = ":%02X%s%s" % (len(cmd) + 1, self.node, cmd_s) - if self.debug != 0: - logger.debug("ELFLOW.write() %s" % str(cmd_s)) - self._intf.write(cmd_s) + if time.time() - self.pre_time < 1.0: + time.sleep(1.0) + self._intf.write(str(cmd)) + self.pre_time = time.time() def read(self): - ret_s = self._intf.read() - if self.debug != 0: - logger.debug("ELFLOW.read() %s" % str(ret_s)) - if len(ret_s) < 5 or ret_s[0] != ":" or ret_s[3:5] != self.node: - logger.debug("ELFLOW.read() format error ret=%s" % str(ret_s)) - return [] - ret_len = int(ret_s[1:3]) - if ret_len * 2 != len(ret_s[3:-2]): - logger.debug("ELFLOW.read() data lenth error ret=%s" % str(ret_s)) - return [] - ret = [] - for i in range(ret_len - 1): - ret.append(int(ret_s[5 + 2 * i:5 + 2 * (i + 1)], 16)) - return ret - - - def get_opening(self): - self._intf.write(self.CMDS['get_valve_opening']) - - def get_flow(self): - self._intf.write(self.CMDS['measure_flow']) - self._intf.readline().decode() - reading = self._intf.readline().decode()[11:-2] - print(reading) - int_flow = int(reading, 16) - print(int_flow) - - - - def get_max_cap(self): - self._intf.write(self.CMDS['read_max_capacity']) + ret = self._intf.read() + if len(ret) < 2 or ret[-2:] != "\r\n": + logger.warning("read() termination error") + return ret.strip() def set_setpoint(self, value): + """value range from 0 - 32000 + """ if not isinstance(value, int): raise ValueError(f"Given value has to be of type integer, is {type(value)}!") - cmd = [1, 1, 0x21, (value >> 8) & 0xFF, value & 0xFF] - self.write(cmd) + hex_val = hex(value)[2:] # [2:] to remove the 0x from the beginning of the hex number + command = f"{self.CMDS['set_setpoint']}" + f"{hex_val.zfill(2)}" # hex should have at least two digits + self._intf.write(command) ret = self.read() - if len(ret) != 3: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 0 and ret[1] == 0 and ret[2] == 5: - return 0 - else: - logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) - return -1 + return ret def get_setpoint(self): - cmd = [4, 1, 0x21, 1, 0x21] - # 06800401210121\r\n - self.write(cmd) + self._intf.write(self.CMDS['get_setpoint']) ret = self.read() - if len(ret) != 5: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 2 and ret[1] == cmd[1] and ret[2] == cmd[2]: - return ((ret[3] << 8) & 0xFF00) | (ret[4] & 0xFF) - else: - logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) - return -1 - - def set_control_mode(self, value): + answer_in_hex = ret[11:] # read from the 11th digits to translate what mode is on + answer = int(answer_in_hex, 16) + return answer + + def set_mode(self, value): """ 0 setpoint source RS232 3 valve close - 4 freeze valuve out + 4 freeze valve out 8 valve fully open - 20 valve steering (valve=setpoint)""" - cmd = [1, 1, 4, value & 0xFF] - self.write(cmd) + 20 valve steering """ + hex_val = hex(value)[2:] # [2:] to remove the 0x from the beginning of the hex number + command = f"{self.CMDS['set_control_mode']}" + f"{hex_val.zfill(2)}" # hex should have at least two digits + self._intf.write(command) ret = self.read() - if len(ret) != 3: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 0 and ret[1] == 0 and ret[2] == 4: - return 0 - else: - logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) - return -1 - - def get_control_mode(self): - cmd = [4, 1, 1, 1, 4] - self.write(cmd) - ret = self.read() - if len(ret) != 4: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 2 and ret[1] == cmd[1] and ret[2] == cmd[2]: - return ret[3] - else: - logger.debug("ELFLOW.set_setpoint() ret error ret=%s" % str(ret)) - return -1 - - def set_valve_output(self, value): - cmd = [1, 114, 0x41, (value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF] - self.write(cmd) - ret = self.read() - if len(ret) != 3: - logger.debug("ELFLOW.set_valve_output() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 0 and ret[1] == 0 and ret[2] == 7: - return 0 - else: - logger.debug("ELFLOW.set_valve_output() ret error ret=%s" % str(ret)) - return -1 - - def get_valve_output(self): - cmd = [4, 114, 0x41, 114, 0x41] - self.write(cmd) - ret = self.read() - if len(ret) != 7: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 2 and ret[1] == cmd[1] and ret[2] == cmd[2]: - return ((ret[3] << 24) & 0xFF000000) | ((ret[4] << 16) & 0xFF0000) | ((ret[5] << 8) & 0xFF00) | (ret[6] & 0xFF) - else: - logger.debug("ELFLOW.get_valve_output() ret error ret=%s" % str(ret)) - return -1 - - def set_controller_speed(self, value): - value = struct.unpack('> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF] - self.write(cmd) - ret = self.read() - if len(ret) != 3: - logger.debug("ELFLOW.set_controller_speed() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 0 and ret[1] == 0 and ret[2] == 7: - return 0 - else: - logger.debug("ELFLOW.set_controller_speed() ret error ret=%s" % str(ret)) - return -1 - - def get_controller_speed(self): - cmd = [4, 114, 0x41, 114, 0x40 + 30] - self.write(cmd) - ret = self.read() - if len(ret) != 7: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 2 and ret[1] == cmd[1] and ret[2] == cmd[2]: - return struct.unpack('!f', chr(ret[3]) + chr(ret[4]) + chr(ret[5]) + chr(ret[6]))[0] - else: - logger.debug("ELFLOW.get_valve_output() ret error ret=%s" % str(ret)) - return -1 - - def get_measure(self): - cmd = [4, 1, 0x21, 1, 0x20] - # 06800401210120\r\n - self.write(cmd) + return ret + + def get_mode(self): + self._intf.write(self.CMDS['get_control_mode']) ret = self.read() - if len(ret) != 5: - logger.debug("ELFLOW.set_setpoint() data lenth error ret=%s" % str(ret)) - return -1 - elif ret[0] == 2 and ret[1] == cmd[1] and ret[2] == cmd[2]: - return ((ret[3] << 8) & 0xFF00) | (ret[4] & 0xFF) - else: - logger.debug("ELFLOW.get_valve_output() ret error ret=%s" % str(ret)) - return -1 - - def get_max_capacity(self): - cmd = [4, 1, 0x4D, 1, 0x4D] - # 068004014D014D\r\n - self.write(cmd) + answer_in_hex = ret[11:] # read from the 11th digits to translate what mode is on + answer = int(answer_in_hex, 16) + return answer + + def get_flow(self): + """This should give the flow in l/min + """ + + # first get the max capacity in % + self._intf.write(self.CMDS['get_capacity']) ret = self.read() - print(ret) + answer_in_hex = ret[11:] # read from the 11th digits to translate what mode is on + cap_100 = struct.unpack('!f', bytes.fromhex(answer_in_hex))[0] + + # now measure the flow + self._intf.write(self.CMDS['get_measure_flow']) + ret1 = self.read() + answer_in_hex = ret1[11:] # read from the 11th digits to translate what mode is on + answer = int(answer_in_hex, 16) + + val = answer / 32000 * cap_100 + return val From bdd1a4f9b32e6261bb58ff87b6edc6c65e2df38a Mon Sep 17 00:00:00 2001 From: AntonioT7 Date: Tue, 14 Mar 2023 15:55:53 +0100 Subject: [PATCH 10/21] corrected some comments --- basil/HL/bronkhorst_elflow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 4e5aac6db..7616ea799 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -67,7 +67,7 @@ def set_setpoint(self, value): def get_setpoint(self): self._intf.write(self.CMDS['get_setpoint']) ret = self.read() - answer_in_hex = ret[11:] # read from the 11th digits to translate what mode is on + answer_in_hex = ret[11:] # read from the 11th digits to translate what point is set answer = int(answer_in_hex, 16) return answer @@ -97,13 +97,13 @@ def get_flow(self): # first get the max capacity in % self._intf.write(self.CMDS['get_capacity']) ret = self.read() - answer_in_hex = ret[11:] # read from the 11th digits to translate what mode is on + answer_in_hex = ret[11:] # read from the 11th digits to translate what the capacity is cap_100 = struct.unpack('!f', bytes.fromhex(answer_in_hex))[0] # now measure the flow self._intf.write(self.CMDS['get_measure_flow']) ret1 = self.read() - answer_in_hex = ret1[11:] # read from the 11th digits to translate what mode is on + answer_in_hex = ret1[11:] answer = int(answer_in_hex, 16) val = answer / 32000 * cap_100 From 31d201319162e3593d8007054c66870b98427a30 Mon Sep 17 00:00:00 2001 From: silab Date: Fri, 7 Jun 2024 13:17:36 +0200 Subject: [PATCH 11/21] FIX: fix set_setpoint --- basil/HL/bronkhorst_elflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 7616ea799..05f0552eb 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -59,7 +59,7 @@ def set_setpoint(self, value): raise ValueError(f"Given value has to be of type integer, is {type(value)}!") hex_val = hex(value)[2:] # [2:] to remove the 0x from the beginning of the hex number - command = f"{self.CMDS['set_setpoint']}" + f"{hex_val.zfill(2)}" # hex should have at least two digits + command = f"{self.CMDS['set_setpoint']}" + f"{hex_val.zfill(4)}" # hex should have at least 4 digits self._intf.write(command) ret = self.read() return ret From c28940ff3b1624e72b94651591a90089f3bf112c Mon Sep 17 00:00:00 2001 From: silab Date: Fri, 7 Jun 2024 13:45:36 +0200 Subject: [PATCH 12/21] ENH: fix added get_valve_output --- basil/HL/bronkhorst_elflow.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 05f0552eb..fe7c66255 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -28,6 +28,7 @@ class Bronkhorst_ELFLOW(HardwareLayer): 'set_control_mode': ':0580010104', 'set_setpoint': ':0680010121', 'get_setpoint': ':06800401210121', + 'get_valve': ':06800472417241', } def __init__(self, intf, conf): @@ -51,6 +52,11 @@ def read(self): logger.warning("read() termination error") return ret.strip() + def get_valve_output(self): + self._intf.write(self.CMDS['get_valve']) + ret = int(self.read()[11:], 16) + return ret*61.7/10345949 # converts int in percentage + def set_setpoint(self, value): """value range from 0 - 32000 """ From 3e4a833b9dfca26ecb6fc7024f4616a63249a18b Mon Sep 17 00:00:00 2001 From: silab Date: Fri, 7 Jun 2024 13:48:58 +0200 Subject: [PATCH 13/21] Added basic example --- examples/lab_devices/bronkhorsteflow.py | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 examples/lab_devices/bronkhorsteflow.py diff --git a/examples/lab_devices/bronkhorsteflow.py b/examples/lab_devices/bronkhorsteflow.py new file mode 100644 index 000000000..6110e9541 --- /dev/null +++ b/examples/lab_devices/bronkhorsteflow.py @@ -0,0 +1,31 @@ +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +''' This script shows how to use EFLOW +''' + +import time +from basil.dut import Dut + +dut = Dut('bronkhorstELFLOW_pyserial.yaml') +dut.init() + +# setting set point +dut["hot_n2"].set_mode(0) +dut["hot_n2"].set_setpoint(10000) +dut["hot_n2"].set_mode(0) +print("setpoint",dut["hot_n2"].get_setpoint()) + +# controlling valve +dut["hot_n2"].set_mode(20) + +# measuring flow rate +# print("Flow",dut["hot_n2"].get_flow()) + +# Measuring of valve opening in % +valve = dut["hot_n2"].get_valve_output() +print("Valve opened in %", valve) \ No newline at end of file From f2a834c46a9b169a9b4447cb4fb4538877630356 Mon Sep 17 00:00:00 2001 From: silab Date: Fri, 7 Jun 2024 13:56:01 +0200 Subject: [PATCH 14/21] fixing codestyle --- basil/HL/bronkhorst_elflow.py | 2 +- examples/lab_devices/bronkhorsteflow.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index fe7c66255..719efc2d5 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -55,7 +55,7 @@ def read(self): def get_valve_output(self): self._intf.write(self.CMDS['get_valve']) ret = int(self.read()[11:], 16) - return ret*61.7/10345949 # converts int in percentage + return ret*61.7 / 10345949 # converts int in percentage def set_setpoint(self, value): """value range from 0 - 32000 diff --git a/examples/lab_devices/bronkhorsteflow.py b/examples/lab_devices/bronkhorsteflow.py index 6110e9541..e48a326ea 100644 --- a/examples/lab_devices/bronkhorsteflow.py +++ b/examples/lab_devices/bronkhorsteflow.py @@ -8,7 +8,6 @@ ''' This script shows how to use EFLOW ''' -import time from basil.dut import Dut dut = Dut('bronkhorstELFLOW_pyserial.yaml') @@ -16,9 +15,9 @@ # setting set point dut["hot_n2"].set_mode(0) -dut["hot_n2"].set_setpoint(10000) +dut["hot_n2"].set_setpoint(10000) dut["hot_n2"].set_mode(0) -print("setpoint",dut["hot_n2"].get_setpoint()) +print("setpoint", dut["hot_n2"].get_setpoint()) # controlling valve dut["hot_n2"].set_mode(20) @@ -28,4 +27,4 @@ # Measuring of valve opening in % valve = dut["hot_n2"].get_valve_output() -print("Valve opened in %", valve) \ No newline at end of file +print("Valve opened in %", valve) From 254ab2962872ff36fc01aa4e71e19d545273663c Mon Sep 17 00:00:00 2001 From: silab Date: Fri, 7 Jun 2024 14:00:01 +0200 Subject: [PATCH 15/21] fixing codestyle --- basil/HL/bronkhorst_elflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 719efc2d5..ec30a891a 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -55,7 +55,7 @@ def read(self): def get_valve_output(self): self._intf.write(self.CMDS['get_valve']) ret = int(self.read()[11:], 16) - return ret*61.7 / 10345949 # converts int in percentage + return ret * 61.7 / 10345949 # converts int in percentage def set_setpoint(self, value): """value range from 0 - 32000 From 7aa512c29a53f3b0a44fb9958e3ceb4187a84a00 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Nov 2024 15:10:19 +0100 Subject: [PATCH 16/21] MAINT: Change memorized binds to dict to facilitate accessing --- basil/utils/USBBinds.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/basil/utils/USBBinds.py b/basil/utils/USBBinds.py index 353dfcb6a..68e98cb6d 100644 --- a/basil/utils/USBBinds.py +++ b/basil/utils/USBBinds.py @@ -37,7 +37,7 @@ def query_identification(rm, resource, baud_rate, read_termination=None, write_t def find_usb_binds(rm, log, instruments, binds_to_skip=[], - memorized_binds=[], + memorized_binds={}, timeout=1000 * 4 ): """ @@ -54,8 +54,8 @@ def find_usb_binds(rm, log, - 'identification': The identification string for the instrument. binds_to_skip (list, optional): List of binds to skip during the search. Defaults to an empty list. - memorized_binds (list, optional): List of memorized binds. - Defaults to an empty list. + memorized_binds (dict, optional): Dictionary of memorized binds. + Defaults to an empty dictionary. timeout (int, optional): Timeout value in milliseconds. Defaults to 4000. @@ -97,14 +97,13 @@ def find_usb_binds(rm, log, try: log.debug(f"Trying {res} with baud rate {instrument['baud_rate']}") - if any(res in bind for bind in memorized_binds): + if memorized_binds.get(res): log.debug(f"Found memorized bind {res}") result = memorized_binds[res] else: result = query_identification(rm, res, instrument['baud_rate'], instrument['read_termination'], instrument['write_termination'], timeout=timeout) - memorized_binds.append({res, result}) - + memorized_binds[res] = result log.debug(f"Found {result.strip()}") if result.lower().strip() in [inst["identification"].lower().strip() for inst in instruments]: From babed48f1de4c9f38d13da65119d4b9354ed38d4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 28 Nov 2024 15:12:34 +0100 Subject: [PATCH 17/21] FIX: Fix a bug where searching for a device is stopped if a different device was found with the same baudrate --- basil/utils/USBBinds.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/basil/utils/USBBinds.py b/basil/utils/USBBinds.py index 68e98cb6d..b6e6c3bbd 100644 --- a/basil/utils/USBBinds.py +++ b/basil/utils/USBBinds.py @@ -106,19 +106,25 @@ def find_usb_binds(rm, log, memorized_binds[res] = result log.debug(f"Found {result.strip()}") - if result.lower().strip() in [inst["identification"].lower().strip() for inst in instruments]: - substring = res.split("/")[2].split("::")[0] + for inst in instruments: + if result.lower().strip() in inst["identification"].lower().strip(): + substring = res.split("/")[2].split("::")[0] - log.info(f"Matched instrument {instrument['identification']} to /dev/{str(substring)}") - skip_binds.append(f"/dev/{str(substring)}") + log.info(f"Matched instrument {inst['identification']} to /dev/{str(substring)}") + skip_binds.append(f"/dev/{str(substring)}") - results[result.lower().strip()] = f"/dev/{str(substring)}" + results[result.lower().strip()] = f"/dev/{str(substring)}" - if len(results) == len(instruments): - return results + if len(results) == len(instruments): + return results - log.debug(f"Found {len(results)} out of {len(instruments)}") + log.debug(f"Found {len(results)} out of {len(instruments)}") + break + else: + continue + + if inst["identification"].lower().strip() in instrument["identification"].lower().strip(): break except pyvisa.VisaIOError: From b7cb27e5fba439ad39c6a9c9420f1fe86fcf2525 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 2 Dec 2024 12:35:32 +0100 Subject: [PATCH 18/21] MAINT: Readability changes in accordance with changes requested in MR#220 --- basil/HL/bronkhorst_elflow.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index ec30a891a..5c18341c1 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -73,8 +73,7 @@ def set_setpoint(self, value): def get_setpoint(self): self._intf.write(self.CMDS['get_setpoint']) ret = self.read() - answer_in_hex = ret[11:] # read from the 11th digits to translate what point is set - answer = int(answer_in_hex, 16) + answer = int(ret[11:], 16) # read from the 11th digits to translate what point is set return answer def set_mode(self, value): @@ -92,8 +91,7 @@ def set_mode(self, value): def get_mode(self): self._intf.write(self.CMDS['get_control_mode']) ret = self.read() - answer_in_hex = ret[11:] # read from the 11th digits to translate what mode is on - answer = int(answer_in_hex, 16) + answer = int(ret[11:], 16) # read from the 11th digits to translate what mode is on return answer def get_flow(self): @@ -103,14 +101,12 @@ def get_flow(self): # first get the max capacity in % self._intf.write(self.CMDS['get_capacity']) ret = self.read() - answer_in_hex = ret[11:] # read from the 11th digits to translate what the capacity is - cap_100 = struct.unpack('!f', bytes.fromhex(answer_in_hex))[0] + cap_100 = struct.unpack('!f', bytes.fromhex(ret[11:]))[0] # read from the 11th digits to translate what the capacity is # now measure the flow self._intf.write(self.CMDS['get_measure_flow']) ret1 = self.read() - answer_in_hex = ret1[11:] - answer = int(answer_in_hex, 16) + answer = int(ret1[11:], 16) # convert reply from hex to integer val = answer / 32000 * cap_100 return val From ec75e92c4920f2753736e7d8b72e14c71fb733ae Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 2 Dec 2024 12:39:12 +0100 Subject: [PATCH 19/21] MAINT: Codestyle --- basil/HL/bronkhorst_elflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 5c18341c1..046bae9a5 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -106,7 +106,7 @@ def get_flow(self): # now measure the flow self._intf.write(self.CMDS['get_measure_flow']) ret1 = self.read() - answer = int(ret1[11:], 16) # convert reply from hex to integer + answer = int(ret1[11:], 16) # convert reply from hex to integer val = answer / 32000 * cap_100 return val From f57e1993aabf2d9644cf01f53d8c0f9355e947b4 Mon Sep 17 00:00:00 2001 From: silab Date: Mon, 2 Dec 2024 16:48:12 +0100 Subject: [PATCH 20/21] ADD: Error if value > 32000 and added comments --- basil/HL/bronkhorst_elflow.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index 046bae9a5..b1a16d841 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -19,6 +19,7 @@ class Bronkhorst_ELFLOW(HardwareLayer): ''' Bronkhorst ELFLOW Manual can be found here: https://www.bronkhorst.com/getmedia/77a1438f-e547-4a79-95ad-53e81fd38a97/917027-Manual-RS232-interface.pdf + and here: https://www.bronkhorst.com/getmedia/257147fc-7f5d-4628-9a47-0533cf68ac08/917099-Manual-EL-FLOW-Select.pdf ''' CMDS = { @@ -64,6 +65,10 @@ def set_setpoint(self, value): if not isinstance(value, int): raise ValueError(f"Given value has to be of type integer, is {type(value)}!") + if value > 32000: + raise ValueError(f"The valid range is 0 to 32000, the set value is {value}!. Setting setpoint to 32000") + value = 32000 + hex_val = hex(value)[2:] # [2:] to remove the 0x from the beginning of the hex number command = f"{self.CMDS['set_setpoint']}" + f"{hex_val.zfill(4)}" # hex should have at least 4 digits self._intf.write(command) @@ -97,8 +102,9 @@ def get_mode(self): def get_flow(self): """This should give the flow in l/min """ - - # first get the max capacity in % + # first get the max capacity in capacity unit + # the max capacity depends on e.g the fluid, which can be changed + # Capacity unit is a command, which returns the used unit in hex self._intf.write(self.CMDS['get_capacity']) ret = self.read() cap_100 = struct.unpack('!f', bytes.fromhex(ret[11:]))[0] # read from the 11th digits to translate what the capacity is From 2d1da08e18a96e3adc70b96c602c757a1a28e163 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 11 Feb 2025 16:37:08 +0100 Subject: [PATCH 21/21] MAINT: Add a comment explaining the cap_100 variable --- basil/HL/bronkhorst_elflow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/basil/HL/bronkhorst_elflow.py b/basil/HL/bronkhorst_elflow.py index b1a16d841..89050ae2c 100644 --- a/basil/HL/bronkhorst_elflow.py +++ b/basil/HL/bronkhorst_elflow.py @@ -104,6 +104,7 @@ def get_flow(self): """ # first get the max capacity in capacity unit # the max capacity depends on e.g the fluid, which can be changed + # cap_100 represents the maximum flow through the fully open valve measured in the capacity unit of the chosen fluid # Capacity unit is a command, which returns the used unit in hex self._intf.write(self.CMDS['get_capacity']) ret = self.read()