mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 21:11:12 +00:00
Update runze pump format
This commit is contained in:
@@ -1,10 +1,9 @@
|
|||||||
import asyncio
|
|
||||||
from threading import Lock, Event
|
from threading import Lock, Event
|
||||||
from enum import Enum
|
|
||||||
from dataclasses import dataclass
|
|
||||||
import time
|
import time
|
||||||
import traceback
|
from dataclasses import dataclass
|
||||||
from typing import Any, Union, Optional, overload
|
from enum import Enum
|
||||||
|
from threading import Lock, Event
|
||||||
|
from typing import Union, Optional
|
||||||
|
|
||||||
import serial.tools.list_ports
|
import serial.tools.list_ports
|
||||||
from serial import Serial
|
from serial import Serial
|
||||||
@@ -18,47 +17,47 @@ class RunzeSyringePumpMode(Enum):
|
|||||||
|
|
||||||
|
|
||||||
pulse_freq_grades = {
|
pulse_freq_grades = {
|
||||||
6000: "0" ,
|
6000: "0",
|
||||||
5600: "1" ,
|
5600: "1",
|
||||||
5000: "2" ,
|
5000: "2",
|
||||||
4400: "3" ,
|
4400: "3",
|
||||||
3800: "4" ,
|
3800: "4",
|
||||||
3200: "5" ,
|
3200: "5",
|
||||||
2600: "6" ,
|
2600: "6",
|
||||||
2200: "7" ,
|
2200: "7",
|
||||||
2000: "8" ,
|
2000: "8",
|
||||||
1800: "9" ,
|
1800: "9",
|
||||||
1600: "10",
|
1600: "10",
|
||||||
1400: "11",
|
1400: "11",
|
||||||
1200: "12",
|
1200: "12",
|
||||||
1000: "13",
|
1000: "13",
|
||||||
800 : "14",
|
800: "14",
|
||||||
600 : "15",
|
600: "15",
|
||||||
400 : "16",
|
400: "16",
|
||||||
200 : "17",
|
200: "17",
|
||||||
190 : "18",
|
190: "18",
|
||||||
180 : "19",
|
180: "19",
|
||||||
170 : "20",
|
170: "20",
|
||||||
160 : "21",
|
160: "21",
|
||||||
150 : "22",
|
150: "22",
|
||||||
140 : "23",
|
140: "23",
|
||||||
130 : "24",
|
130: "24",
|
||||||
120 : "25",
|
120: "25",
|
||||||
110 : "26",
|
110: "26",
|
||||||
100 : "27",
|
100: "27",
|
||||||
90 : "28",
|
90: "28",
|
||||||
80 : "29",
|
80: "29",
|
||||||
70 : "30",
|
70: "30",
|
||||||
60 : "31",
|
60: "31",
|
||||||
50 : "32",
|
50: "32",
|
||||||
40 : "33",
|
40: "33",
|
||||||
30 : "34",
|
30: "34",
|
||||||
20 : "35",
|
20: "35",
|
||||||
18 : "36",
|
18: "36",
|
||||||
16 : "37",
|
16: "37",
|
||||||
14 : "38",
|
14: "38",
|
||||||
12 : "39",
|
12: "39",
|
||||||
10 : "40",
|
10: "40",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +69,7 @@ class RunzeSyringePumpConnectionError(Exception):
|
|||||||
class RunzeSyringePumpInfo:
|
class RunzeSyringePumpInfo:
|
||||||
port: str
|
port: str
|
||||||
address: str = "1"
|
address: str = "1"
|
||||||
|
|
||||||
max_volume: float = 25.0
|
max_volume: float = 25.0
|
||||||
mode: RunzeSyringePumpMode = RunzeSyringePumpMode.Normal
|
mode: RunzeSyringePumpMode = RunzeSyringePumpMode.Normal
|
||||||
|
|
||||||
@@ -82,16 +81,16 @@ class RunzeSyringePump:
|
|||||||
def __init__(self, port: str, address: str = "1", max_volume: float = 25.0, mode: RunzeSyringePumpMode = None):
|
def __init__(self, port: str, address: str = "1", max_volume: float = 25.0, mode: RunzeSyringePumpMode = None):
|
||||||
self.port = port
|
self.port = port
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
||||||
self.max_volume = max_volume
|
self.max_volume = max_volume
|
||||||
self.total_steps = self.total_steps_vel = 6000
|
self.total_steps = self.total_steps_vel = 6000
|
||||||
|
|
||||||
self._status = "Idle"
|
self._status = "Idle"
|
||||||
self._mode = mode
|
self._mode = mode
|
||||||
self._max_velocity = 0
|
self._max_velocity = 0
|
||||||
self._valve_position = "I"
|
self._valve_position = "I"
|
||||||
self._position = 0
|
self._position = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# if port in serial_ports and serial_ports[port].is_open:
|
# if port in serial_ports and serial_ports[port].is_open:
|
||||||
# self.hardware_interface = serial_ports[port]
|
# self.hardware_interface = serial_ports[port]
|
||||||
@@ -100,11 +99,8 @@ class RunzeSyringePump:
|
|||||||
# baudrate=9600,
|
# baudrate=9600,
|
||||||
# port=port
|
# port=port
|
||||||
# )
|
# )
|
||||||
self.hardware_interface = Serial(
|
self.hardware_interface = Serial(baudrate=9600, port=port)
|
||||||
baudrate=9600,
|
|
||||||
port=port
|
|
||||||
)
|
|
||||||
|
|
||||||
except (OSError, SerialException) as e:
|
except (OSError, SerialException) as e:
|
||||||
# raise RunzeSyringePumpConnectionError from e
|
# raise RunzeSyringePumpConnectionError from e
|
||||||
self.hardware_interface = port
|
self.hardware_interface = port
|
||||||
@@ -114,13 +110,13 @@ class RunzeSyringePump:
|
|||||||
self._error_event = Event()
|
self._error_event = Event()
|
||||||
self._query_lock = Lock()
|
self._query_lock = Lock()
|
||||||
self._run_lock = Lock()
|
self._run_lock = Lock()
|
||||||
|
|
||||||
def _adjust_total_steps(self):
|
def _adjust_total_steps(self):
|
||||||
self.total_steps = 6000 if self.mode == RunzeSyringePumpMode.Normal else 48000
|
self.total_steps = 6000 if self.mode == RunzeSyringePumpMode.Normal else 48000
|
||||||
self.total_steps_vel = 48000 if self.mode == RunzeSyringePumpMode.AccuratePosVel else 6000
|
self.total_steps_vel = 48000 if self.mode == RunzeSyringePumpMode.AccuratePosVel else 6000
|
||||||
|
|
||||||
def send_command(self, full_command: str):
|
def send_command(self, full_command: str):
|
||||||
full_command_data = bytearray(full_command, 'ascii')
|
full_command_data = bytearray(full_command, "ascii")
|
||||||
response = self.hardware_interface.write(full_command_data)
|
response = self.hardware_interface.write(full_command_data)
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
output = self._receive(self.hardware_interface.read_until(b"\n"))
|
output = self._receive(self.hardware_interface.read_until(b"\n"))
|
||||||
@@ -131,9 +127,9 @@ class RunzeSyringePump:
|
|||||||
if self._closing:
|
if self._closing:
|
||||||
raise RunzeSyringePumpConnectionError
|
raise RunzeSyringePumpConnectionError
|
||||||
|
|
||||||
run = 'R' if not "?" in command else ''
|
run = "R" if "?" not in command else ""
|
||||||
full_command = f"/{self.address}{command}{run}\r\n"
|
full_command = f"/{self.address}{command}{run}\r\n"
|
||||||
|
|
||||||
output = self.send_command(full_command)[3:-3]
|
output = self.send_command(full_command)[3:-3]
|
||||||
return output
|
return output
|
||||||
|
|
||||||
@@ -161,7 +157,7 @@ class RunzeSyringePump:
|
|||||||
time.sleep(0.5) # Wait for 0.5 seconds before polling again
|
time.sleep(0.5) # Wait for 0.5 seconds before polling again
|
||||||
|
|
||||||
status = self.get_status()
|
status = self.get_status()
|
||||||
if status == 'Idle':
|
if status == "Idle":
|
||||||
break
|
break
|
||||||
finally:
|
finally:
|
||||||
pass
|
pass
|
||||||
@@ -177,7 +173,7 @@ class RunzeSyringePump:
|
|||||||
# # self.set_mode(self.mode)
|
# # self.set_mode(self.mode)
|
||||||
# self.mode = self.get_mode()
|
# self.mode = self.get_mode()
|
||||||
return response
|
return response
|
||||||
|
|
||||||
# Settings
|
# Settings
|
||||||
|
|
||||||
def set_baudrate(self, baudrate):
|
def set_baudrate(self, baudrate):
|
||||||
@@ -187,32 +183,32 @@ class RunzeSyringePump:
|
|||||||
return self._run("U47")
|
return self._run("U47")
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unsupported baudrate")
|
raise ValueError("Unsupported baudrate")
|
||||||
|
|
||||||
# Device Status
|
# Device Status
|
||||||
@property
|
@property
|
||||||
def status(self) -> str:
|
def status(self) -> str:
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
def _standardize_status(self, status_raw):
|
def _standardize_status(self, status_raw):
|
||||||
return "Idle" if status_raw == "`" else "Busy"
|
return "Idle" if status_raw == "`" else "Busy"
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
status_raw = self._query("Q")
|
status_raw = self._query("Q")
|
||||||
self._status = self._standardize_status(status_raw)
|
self._status = self._standardize_status(status_raw)
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
# Mode Settings and Queries
|
# Mode Settings and Queries
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mode(self) -> int:
|
def mode(self) -> int:
|
||||||
return self._mode
|
return self._mode
|
||||||
|
|
||||||
# def set_mode(self, mode: RunzeSyringePumpMode):
|
# def set_mode(self, mode: RunzeSyringePumpMode):
|
||||||
# self.mode = mode
|
# self.mode = mode
|
||||||
# self._adjust_total_steps()
|
# self._adjust_total_steps()
|
||||||
# command = f"N{mode.value}"
|
# command = f"N{mode.value}"
|
||||||
# return self._run(command)
|
# return self._run(command)
|
||||||
|
|
||||||
# def get_mode(self):
|
# def get_mode(self):
|
||||||
# response = self._query("?28")
|
# response = self._query("?28")
|
||||||
# status_raw, mode = response[0], int(response[1])
|
# status_raw, mode = response[0], int(response[1])
|
||||||
@@ -221,11 +217,11 @@ class RunzeSyringePump:
|
|||||||
# return self.mode
|
# return self.mode
|
||||||
|
|
||||||
# Speed Settings and Queries
|
# Speed Settings and Queries
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_velocity(self) -> float:
|
def max_velocity(self) -> float:
|
||||||
return self._max_velocity
|
return self._max_velocity
|
||||||
|
|
||||||
def set_max_velocity(self, velocity: float):
|
def set_max_velocity(self, velocity: float):
|
||||||
self._max_velocity = velocity
|
self._max_velocity = velocity
|
||||||
pulse_freq = int(velocity / self.max_volume * self.total_steps_vel)
|
pulse_freq = int(velocity / self.max_volume * self.total_steps_vel)
|
||||||
@@ -238,10 +234,10 @@ class RunzeSyringePump:
|
|||||||
self._status = self._standardize_status(status_raw)
|
self._status = self._standardize_status(status_raw)
|
||||||
self._max_velocity = pulse_freq / self.total_steps_vel * self.max_volume
|
self._max_velocity = pulse_freq / self.total_steps_vel * self.max_volume
|
||||||
return self._max_velocity
|
return self._max_velocity
|
||||||
|
|
||||||
def set_velocity_grade(self, velocity: Union[int, str]):
|
def set_velocity_grade(self, velocity: Union[int, str]):
|
||||||
return self._run(f"S{velocity}")
|
return self._run(f"S{velocity}")
|
||||||
|
|
||||||
def get_velocity_grade(self):
|
def get_velocity_grade(self):
|
||||||
response = self._query("?2")
|
response = self._query("?2")
|
||||||
status_raw, pulse_freq = response[0], int(response[1:])
|
status_raw, pulse_freq = response[0], int(response[1:])
|
||||||
@@ -265,21 +261,21 @@ class RunzeSyringePump:
|
|||||||
self._status = self._standardize_status(status_raw)
|
self._status = self._standardize_status(status_raw)
|
||||||
velocity = pulse_freq / self.total_steps_vel * self.max_volume
|
velocity = pulse_freq / self.total_steps_vel * self.max_volume
|
||||||
return pulse_freq, velocity
|
return pulse_freq, velocity
|
||||||
|
|
||||||
# Operations
|
# Operations
|
||||||
|
|
||||||
# Valve Setpoint and Queries
|
# Valve Setpoint and Queries
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def valve_position(self) -> str:
|
def valve_position(self) -> str:
|
||||||
return self._valve_position
|
return self._valve_position
|
||||||
|
|
||||||
def set_valve_position(self, position: Union[int, str, float]):
|
def set_valve_position(self, position: Union[int, str, float]):
|
||||||
if type(position) == float:
|
if isinstance(position, float):
|
||||||
position = round(position / 120)
|
position = round(position / 120)
|
||||||
command = f"I{position}" if type(position) == int or ord(position) <= 57 else position.upper()
|
command = f"I{position}" if isinstance(position, int) or ord(position) <= 57 else position.upper()
|
||||||
response = self._run(command)
|
response = self._run(command)
|
||||||
self._valve_position = f"{position}" if type(position) == int or ord(position) <= 57 else position.upper()
|
self._valve_position = f"{position}" if isinstance(position, int) or ord(position) <= 57 else position.upper()
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def get_valve_position(self) -> str:
|
def get_valve_position(self) -> str:
|
||||||
@@ -288,9 +284,9 @@ class RunzeSyringePump:
|
|||||||
self._valve_position = pos_valve
|
self._valve_position = pos_valve
|
||||||
self._status = self._standardize_status(status_raw)
|
self._status = self._standardize_status(status_raw)
|
||||||
return pos_valve
|
return pos_valve
|
||||||
|
|
||||||
# Plunger Setpoint and Queries
|
# Plunger Setpoint and Queries
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def position(self) -> float:
|
def position(self) -> float:
|
||||||
return self._position
|
return self._position
|
||||||
@@ -321,7 +317,7 @@ class RunzeSyringePump:
|
|||||||
velocity_cmd = ""
|
velocity_cmd = ""
|
||||||
pos_step = int(position / self.max_volume * self.total_steps)
|
pos_step = int(position / self.max_volume * self.total_steps)
|
||||||
return self._run(f"{velocity_cmd}A{pos_step}")
|
return self._run(f"{velocity_cmd}A{pos_step}")
|
||||||
|
|
||||||
def pull_plunger(self, volume: float):
|
def pull_plunger(self, volume: float):
|
||||||
"""
|
"""
|
||||||
Pull a fixed volume (unit: ml)
|
Pull a fixed volume (unit: ml)
|
||||||
@@ -334,7 +330,7 @@ class RunzeSyringePump:
|
|||||||
"""
|
"""
|
||||||
pos_step = int(volume / self.max_volume * self.total_steps)
|
pos_step = int(volume / self.max_volume * self.total_steps)
|
||||||
return self._run(f"P{pos_step}")
|
return self._run(f"P{pos_step}")
|
||||||
|
|
||||||
def push_plunger(self, volume: float):
|
def push_plunger(self, volume: float):
|
||||||
"""
|
"""
|
||||||
Push a fixed volume (unit: ml)
|
Push a fixed volume (unit: ml)
|
||||||
@@ -355,7 +351,7 @@ class RunzeSyringePump:
|
|||||||
|
|
||||||
def stop_operation(self):
|
def stop_operation(self):
|
||||||
return self._run("T")
|
return self._run("T")
|
||||||
|
|
||||||
# Queries
|
# Queries
|
||||||
|
|
||||||
def query_command_buffer_status(self):
|
def query_command_buffer_status(self):
|
||||||
@@ -391,4 +387,4 @@ class RunzeSyringePump:
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
r = RunzeSyringePump("/dev/tty.usbserial-D30JUGG5", "1", 25.0)
|
r = RunzeSyringePump("/dev/tty.usbserial-D30JUGG5", "1", 25.0)
|
||||||
r.initialize()
|
r.initialize()
|
||||||
|
|||||||
@@ -176,6 +176,9 @@ class RunzeMultiplePump:
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
def _receive(self, data: bytes) -> str:
|
def _receive(self, data: bytes) -> str:
|
||||||
|
"""
|
||||||
|
Do not change this method.
|
||||||
|
"""
|
||||||
if not data:
|
if not data:
|
||||||
return ""
|
return ""
|
||||||
ascii_string = "".join(chr(byte) for byte in data)
|
ascii_string = "".join(chr(byte) for byte in data)
|
||||||
|
|||||||
Reference in New Issue
Block a user