Source code for dlab.hardware.wrappers.piezojena_controller
import serial
import time
V_MIN = 0.0
V_MAX = 140.0
RANGE_UM = 100.0
[docs]
class NV40:
ERRORS = {
'err,1': 'Unknown command',
'err,2': 'Too many characters in the command',
'err,3': 'Too many characters in the parameter',
'err,4': 'Too many parameters',
'err,5': 'Wrong character in parameter',
'err,6': 'Wrong separator',
'err,7': 'Position out of range',
}
def __init__(self, port, timeout=0.05, closed_loop=False):
self.ser = serial.Serial(
port=port,
baudrate=9600,
bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE,
parity=serial.PARITY_NONE,
timeout=timeout,
write_timeout=0.05,
)
time.sleep(0.05)
self.set_remote_control(True)
if closed_loop:
raise RuntimeError(
"Closed-loop mode is not supported on this NV40."
)
self._send("ol")
[docs]
def close(self):
if self.ser and self.ser.is_open:
self.ser.close()
def __del__(self):
try:
self.close()
except:
pass
def _send(self, cmd: str):
self.ser.write((cmd + "\r").encode())
def _query(self, cmd: str) -> str:
self.ser.reset_input_buffer()
self.ser.write((cmd + "\r").encode())
ans = self.ser.readline().decode(errors="ignore").strip()
if ans in self.ERRORS:
raise ValueError(self.ERRORS[ans])
return ans
[docs]
def set_remote_control(self, enable=True):
self._send("i1" if enable else "i0")
[docs]
def set_closed_loop(self, enable=True):
if enable:
raise RuntimeError("Closed loop not supported.")
self._send("ol")
[docs]
def set_position(self, value: float):
value = max(V_MIN, min(V_MAX, value))
self._send(f"wr,{value:.3f}")
[docs]
def get_position(self) -> float:
ans = self._query("rd")
try:
return float(ans.split(",")[1])
except:
return float('nan')
[docs]
@classmethod
def get_voltage_limits(cls):
return V_MIN, V_MAX
if __name__ == "__main__":
dev = NV40("COM6")
import numpy as np
for v in np.arange(10, 11, 0.1):
dev.set_position(v)
time.sleep(0.05)
print(v, dev.get_position())
dev.close()