# coding: utf-8
from multiprocessing import Lock
from .actuator import Actuator
from .._global import OptionalModule
try:
import serial
except (ModuleNotFoundError, ImportError):
serial = OptionalModule("pyserial")
[docs]class Servostar(Actuator):
"""To drive and configure a servostar variator through a serial
connection."""
[docs] def __init__(self, device, baudrate=38400, mode="serial"):
"""Sets the instance attributes.
Args:
device (:obj:`str`, optional): Path to connect to the serial port.
baudrate (:obj:`int`, optional): Set the corresponding baud rate.
mode (:obj:`str`, optional): Can be `'analog'` or `'serial'`.
"""
Actuator.__init__(self)
self.devname = device
self.mode = mode
self.baud = baudrate
self.lock = Lock()
self.last = None
def open(self):
self.lock.acquire()
self.ser = serial.Serial(self.devname, baudrate=self.baud, timeout=2)
self.ser.flushInput()
self.ser.write('ANCNFG 0\r\n')
self.lock.release()
if self.mode == "analog":
self.set_mode_analog()
elif self.mode == "serial":
self.set_mode_serial()
else:
raise AttributeError("No such mode: " + str(self.mode))
self.lock.acquire()
self.ser.write('EN\r\n')
self.ser.write('MH\r\n')
self.lock.release()
[docs] def set_position(self, pos, speed=20000, acc=200, dec=200):
"""Go to the position specified at the given speed and acceleration."""
if self.last is pos:
return
if isinstance(pos, bool):
# To use set_position(True) as set_mode_serial()
# and set_position(False) as set_mode_analog()
# (to command all of this from as single generator)
if pos:
self.set_mode_serial()
else:
self.set_mode_analog()
elif self.mode != "serial":
self.set_mode_serial()
self.lock.acquire()
self.ser.flushInput()
self.ser.write(" ".join(["ORDER 0", str(int(pos)), str(speed),
"8192", str(acc), str(dec), "0 0 0 0\r\n"]))
self.ser.write("MOVE 0\r\n") # activates the order
self.lock.release()
self.last = pos
[docs] def get_position(self):
"""Reads current position.
Returns:
Current position of the motor.
"""
self.lock.acquire()
self.ser.flushInput()
self.ser.write("PFB\r\n")
r = ''
while r != "PFB\r\n":
if len(r) == 5:
r = r[1:]
r += self.ser.read()
if not r:
print("Servostar timeout error! make sure the servostar is on!")
self.lock.release()
return
r = ''
while "\n" not in r:
r += self.ser.read()
self.lock.release()
return int(r)
[docs] def set_mode_serial(self):
"""Sets the serial input as setpoint."""
self.lock.acquire()
self.ser.flushInput()
self.ser.write('OPMODE 8\r\n')
self.lock.release()
self.mode = "serial"
[docs] def set_mode_analog(self):
"""Sets the analog input as setpoint."""
self.last = None
self.lock.acquire()
self.ser.flushInput()
self.ser.write('OPMODE 1\r\n')
self.lock.release()
self.mode = "analog"
[docs] def clear_errors(self):
"""Clears error in motor registers."""
self.ser.flushInput()
self.ser.write("CLRFAULT\r\n")
[docs] def stop(self):
"""Stops the motor."""
self.ser.write("DIS\r\n")
self.ser.flushInput()
def close(self):
self.ser.close()