Skip to content

Commit

Permalink
add python package, add gitignore
Browse files Browse the repository at this point in the history
  • Loading branch information
lrlunin committed Jul 27, 2023
1 parent 807769c commit 5b6401d
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 72 deletions.
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
__pycache__/
.DS_Store
.vscode
site/

# Distribution / packaging
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
22 changes: 22 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from setuptools import setup, find_packages

setup(
name="tangods_brookssla",
version="0.0.1",
description="Tango Device for Brooks",
author="Marin Hennecke",
author_email="[email protected]",
python_requires=">=3.6",
entry_points={"console_scripts": ["BrooksSLA = tangods_brookssla:main"]},
license="MIT",
packages=["tangods_brookssla"],
install_requires=[
"pytango",
],
url="https://github.com/MBI-Div-b/pytango-BrooksSLA",
keywords=[
"tango device",
"tango",
"pytango",
],
)
86 changes: 43 additions & 43 deletions Brooks.py → tangods_brookssla/Brooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,136 +5,136 @@
import serial
from six import b, indexbytes


class Brooks(object):
""" Driver for Brooks s-protocol """
def __init__(self, device, port='/dev/ttyUSB0'):
"""Driver for Brooks s-protocol"""

def __init__(self, device, port="/dev/ttyUSB0"):
self.ser = serial.Serial(port, 19200)
self.ser.parity = serial.PARITY_ODD
self.ser.bytesize = serial.EIGHTBITS
self.ser.stopbits = serial.STOPBITS_ONE
deviceid = self.comm('8280000000000b06'
+ self.pack(device[-8:]))
manufactor_code = '0a'
deviceid = self.comm("8280000000000b06" + self.pack(device[-8:]))
manufactor_code = "0a"
device_type = deviceid[12:14]
long_address = manufactor_code + device_type + deviceid[-6:]
self.long_address = long_address

def pack(self, input_string):
""" Turns a string in packed-ascii format """
#This function lacks basic error checking....
klaf = ''
"""Turns a string in packed-ascii format"""
# This function lacks basic error checking....
klaf = ""
for s in input_string:
klaf += bin((ord(s) % 128) % 64)[2:].zfill(6)
result = ''
result = ""
for i in range(0, 6):
result = result + hex(int('' + klaf[i * 8:i * 8 + 8],
2))[2:].zfill(2)
result = result + hex(int("" + klaf[i * 8 : i * 8 + 8], 2))[2:].zfill(2)
return result

def crc(self, command):
""" Calculate crc value of command """
"""Calculate crc value of command"""
i = 0
while command[i:i + 2] == 'FF':
while command[i : i + 2] == "FF":
i += 2
command = command[i:]
n = len(command)
result = 0
for i in range(0, (n//2)):
byte_string = command[i*2:i*2+2]
for i in range(0, (n // 2)):
byte_string = command[i * 2 : i * 2 + 2]
byte = int(byte_string, 16)
result = byte ^ result
return hex(result)

def comm(self, command):
""" Implements low-level details of the s-protocol """
"""Implements low-level details of the s-protocol"""
check = str(self.crc(command))
check = check[2:].zfill(2)
final_com = 'FFFFFFFF' + command + check
bin_comm = ''
final_com = "FFFFFFFF" + command + check
bin_comm = ""
for i in range(0, len(final_com) // 2):
bin_comm += chr(int(final_com[i * 2:i * 2 + 2], 16))
bin_comm += chr(int(final_com[i * 2 : i * 2 + 2], 16))
bin_comm += chr(0)
bytes_for_serial = b(bin_comm)
error = 1
while (error > 0) and (error < 10):
self.ser.write(bytes_for_serial)
time.sleep(0.2)
s = self.ser.read(self.ser.inWaiting())
st = ''
st = ""
for i in range(0, len(s)):
#char = hex(ord(s[i]))[2:].zfill(2)
#char = hex(s[i])[2:].zfill(2)
# char = hex(ord(s[i]))[2:].zfill(2)
# char = hex(s[i])[2:].zfill(2)
char = hex(indexbytes(s, i))[2:].zfill(2)
if not char.upper() == 'FF':
if not char.upper() == "FF":
st = st + char
try:
# delimiter = st[0:2]
# address = st[2:12]
command = st[12:14]
byte_count = int(st[14:16], 16)
response = st[16:16 + 2 * byte_count]
response = st[16 : 16 + 2 * byte_count]
error = 0
except ValueError:
error = error + 1
response = 'Error'
response = "Error"
return response

def read_flow(self):
""" Read the current flow-rate """
response = self.comm('82' + self.long_address + '0100')
"""Read the current flow-rate"""
response = self.comm("82" + self.long_address + "0100")
try: # TODO: This should be handled be re-sending command
#status_code = response[0:4]
# status_code = response[0:4]
unit_code = int(response[4:6], 16)
flow_code = response[6:]
byte0 = chr(int(flow_code[0:2], 16))
byte1 = chr(int(flow_code[2:4], 16))
byte2 = chr(int(flow_code[4:6], 16))
byte3 = chr(int(flow_code[6:8], 16))
flow = struct.unpack('>f', b(byte0 + byte1 + byte2 + byte3))
flow = struct.unpack(">f", b(byte0 + byte1 + byte2 + byte3))
value = flow[0]
except ValueError:
value = -1
unit_code = 171 # Satisfy assertion check, we know what is wrong
# assert unit_code == 171 # Flow unit should always be mL/min
# print('read flow: ' + value)
# assert unit_code == 171 # Flow unit should always be mL/min
# print('read flow: ' + value)
return value

def read_full_range(self):
"""
Report the full range of the device
Apparantly this does not work for SLA-series...
"""
response = self.comm('82' + self.long_address + '980106')#Command 152
response = self.comm("82" + self.long_address + "980106") # Command 152
# Double check what gas-selection code really means...
# currently 01 is used
# status_code = response[0:4]
unit_code = int(response[4:6], 16)
# assert unit_code == 171 #Flow controller should always be set to mL/min
# assert unit_code == 171 #Flow controller should always be set to mL/min

flow_code = response[6:]
byte0 = chr(int(flow_code[0:2], 16))
byte1 = chr(int(flow_code[2:4], 16))
byte2 = chr(int(flow_code[4:6], 16))
byte3 = chr(int(flow_code[6:8], 16))
max_flow = struct.unpack('>f', byte0 + byte1 + byte2 + byte3)
max_flow = struct.unpack(">f", byte0 + byte1 + byte2 + byte3)
return max_flow[0]

def set_flow(self, flowrate):
""" Set the setpoint of the flow """
ieee = struct.pack('>f', flowrate)
ieee_flowrate = ''
"""Set the setpoint of the flow"""
ieee = struct.pack(">f", flowrate)
ieee_flowrate = ""
for i in range(0, 4):
ieee_flowrate += hex(ieee[i])[2:].zfill(2)
#39 = unit code for percent
#FA = unit code for 'same unit as flowrate measurement'
response = self.comm('82' + self.long_address +
'ec05' + 'FA' + ieee_flowrate)
# 39 = unit code for percent
# FA = unit code for 'same unit as flowrate measurement'
response = self.comm("82" + self.long_address + "ec05" + "FA" + ieee_flowrate)
status_code = response[0:4]
unit_code = int(response[4:6], 16)
# print('set flow: ' + flowrate)
# print('set flow: ' + flowrate)
return status_code, unit_code

if __name__ == '__main__':

if __name__ == "__main__":
BROOKS = Brooks()
print(BROOKS.long_address)
print(BROOKS.read_flow())
54 changes: 25 additions & 29 deletions BrooksSLA.py → tangods_brookssla/BrooksSLA.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# PyTango imports
from tango import DevState, AttrWriteType
from tango.server import run, Device, attribute, device_property

# Additional import
import Brooks as b
from . import Brooks as b


__all__ = ["BrooksSLA", "main"]
Expand All @@ -24,36 +25,29 @@ class BrooksSLA(Device):
# Device Properties
# -----------------

Port = device_property(
dtype='DevString',
doc='e.g., /dev/ttyBrooks'
)

ID = device_property(
dtype='DevString',
doc='12345678'
)
Port = device_property(dtype="DevString", doc="e.g., /dev/ttyBrooks")

ID = device_property(dtype="DevString", doc="12345678")

# ----------
# Attributes
# ----------

Setpoint = attribute(
dtype='DevDouble',
dtype="DevDouble",
access=AttrWriteType.READ_WRITE,
unit="mbar",
memorized=True,
hw_memorized=True,
)
Readback = attribute(
dtype='DevDouble',
dtype="DevDouble",
access=AttrWriteType.READ,
unit="mbar",
)
PID_enable = attribute(
label='PID enable',
dtype='DevBoolean',
label="PID enable",
dtype="DevBoolean",
access=AttrWriteType.READ_WRITE,
)

Expand All @@ -66,30 +60,32 @@ def init_device(self):
self.info_stream("init_device()")
Device.init_device(self)
self.set_state(DevState.INIT)

try:
self.info_stream("Connecting on port: {:s}".format(self.Port))
# connect to device
self.sla = b.Brooks(self.ID, self.Port)
self.info_stream("Connected to device ID: {:s}".format(self.ID))
except:
self.error_stream("Could not connect to device ID {:s} on port {:s}!".format(self.ID, self.Port))
self.error_stream(
"Could not connect to device ID {:s} on port {:s}!".format(
self.ID, self.Port
)
)
self.set_status("The device is in OFF state")
self.set_state(DevState.OFF)

self.__pid_enable = False

self.set_status("The device is in ON state")
self.set_state(DevState.ON)


def always_executed_hook(self):
"""Method always executed before any TANGO command is executed."""

def delete_device(self):
self.set_status("The device is in OFF state")
self.set_state(DevState.OFF)


# ------------------
# Attributes methods
Expand All @@ -99,17 +95,17 @@ def read_Readback(self):
return self.sla.read_flow()

def read_Setpoint(self):
return self.__setpoint
return self.__setpoint

def write_Setpoint(self, value):
self.sla.set_flow(value*self.__pid_enable)
self.__setpoint=value
self.sla.set_flow(value * self.__pid_enable)
self.__setpoint = value

def read_PID_enable(self):
return self.__pid_enable
return self.__pid_enable

def write_PID_enable(self, value):
self.__pid_enable=value
self.__pid_enable = value
self.write_Setpoint(self.__setpoint)

# --------
Expand All @@ -131,5 +127,5 @@ def main(args=None, **kwargs):
return run((BrooksSLA,), args=args, **kwargs)


if __name__ == '__main__':
if __name__ == "__main__":
main()
9 changes: 9 additions & 0 deletions tangods_brookssla/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .BrooksSLA import BrooksSLA


def main():
import sys
import tango.server

args = ["BrooksSLA"] + sys.argv[1:]
tango.server.run((BrooksSLA,), args=args)
3 changes: 3 additions & 0 deletions tangods_brookssla/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import main

main()

0 comments on commit 5b6401d

Please sign in to comment.