class Uart(): def __init__(self, path, baud=115200, read_timeout=1): self.impl = Serial(port=path, baudrate=baud, exclusive=True) self.read_timeout = read_timeout self.impl.reset_input_buffer() self.impl.reset_output_buffer() def __enter__(self, *args): self.impl.__enter__() return self def __exit__(self, *args): self.impl.__exit__() ''' Read data into buffer, return buffer ''' def read(self): # Wait for data to be available self.impl.timeout = self.read_timeout self.impl.read(0) # Read as much data as is available in the buffer self.impl.timeout = 0 return self.impl.read(self.impl.inWaiting()) ''' Write data from buffer ''' def write(self, data): self.impl.write(data)
class Strip(object): def __init__(self,length,port): self._disp_length = length self._s = Serial(port, 115200*4, timeout=0.5) self._bar = [[0, 0, 0]]*self._disp_length self._commit() def blink(self, index, duration=0.1, dutycycle=0.5, color=None): assert duration >= 0 self.set_bit(index, color) time.sleep(duration*dutycycle) self.clear_bit(index) time.sleep(duration*(1 - dutycycle)) def wink(self, index, duration=0.1, dutycycle=0.5): assert duration >= 0 color = self._bar[index - 1] self.clear_bit(index) time.sleep(duration*dutycycle) self.set_bit(index, color) time.sleep(duration*(1 - dutycycle)) def set_bit(self, index, color): """Color is a tuple (R,G,B) where R, G, and B are numbers within [0,1]. Index starts from zero.""" assert index >= 0 and index <= self._disp_length - 1, 'index should be within [0,length-1]' self._bar[index] = color self._commit() def clear_bit(self, index): assert index >= 0 and index <= self._disp_length - 1, 'index should be within [0,length-1]' self.set_bit(index, [0,0,0]) def set_all(self, pixels): assert len(pixels) >= len(self._bar) assert len(pixels[0]) == 3 assert pixels[0][0] >= 0 and pixels[0][0] <= 1 self._bar = list(pixels[0:self._disp_length]) self._commit() def _commit(self): write_led_strip(self._s, self._bar) def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self._s.__exit__() def __del__(self): self._s.__del__()
class MeerstetterTEC_USB(MeerstetterTEC): """ Discrete implementation of the MeerstetterTEC class on an USB based interface """ def __init__(self, port, timeout=1, baudrate=57600, tec_address=0, check_crc=True): super().__init__(tec_address=tec_address, check_crc=check_crc) self.port = port self.timeout = timeout self.baudrate = baudrate self.ser = Serial( port=self.port, timeout=self.timeout, baudrate=self.baudrate, ) def __exit__(self, exc_type, exc_val, exc_tb): self.ser.__exit__(exc_type, exc_val, exc_tb) def __enter__(self): return self def stop(self): self.ser.flush() self.ser.close() def _sendAndReceive(self, frame): byte_arr = frame + b'\r' #clear all remaining buffers self.ser.reset_output_buffer() self.ser.reset_input_buffer() #send and flush self.ser.write(byte_arr) self.ser.flush() #read all in answer_arr = self.ser.read_until(terminator=b'\r') return answer_arr[0:-1]
class Duck: def __init__(self, *serial_device_parameters): self.serial_device = Serial(*serial_device_parameters) init_serial(self.serial_device) def __enter__(self): self.serial_device.__enter__() return self def __exit__(self, *exp): self.serial_device.__exit__(*exp) def run(self, op="NOP", verbose=False, read=True): run_operation(self.serial_device, op, verbose, read) def buffer_ramp(self, dac_channel, adc_channel, begin_voltage, end_voltage, number_of_steps, delay_in_microsecs): return _buffer_ramp(self.serial_device, dac_channel, adc_channel, begin_voltage, end_voltage, number_of_steps, delay_in_microsecs)
class MeCom: """ Main class. Import this one: from qao.devices.mecom import MeCom For a usage example see __main__ """ SEQUENCE_COUNTER = 1 def __init__(self, serialport="/dev/ttyUSB0", timeout=1, baudrate=57600): """ Initialize communication with serial port. :param serialport: str :param timeout: int """ # initialize serial connection self.ser = Serial(port=serialport, timeout=timeout, write_timeout=timeout, baudrate=baudrate) # start protocol thread # self.protocol = ReaderThread(serial_instance=self.ser, protocol_factory=MePacket) # self.receiver = self.protocol.__enter__() # initialize parameters self.PARAMETERS = ParameterList() def __exit__(self, exc_type, exc_val, exc_tb): self.ser.__exit__(exc_type, exc_val, exc_tb) def __enter__(self): return self def stop(self): self.ser.flush() self.ser.close() def _find_parameter(self, parameter_name, parameter_id): """ Return Parameter() with either name or id given. :param parameter_name: str :param parameter_id: int :return: Parameter """ return self.PARAMETERS.get_by_name(parameter_name) if parameter_name is not None\ else self.PARAMETERS.get_by_id(parameter_id) def _inc(self): self.SEQUENCE_COUNTER += 1 @staticmethod def _raise(query): """ If DeviceError is received, raise! :param query: VR or VS :return: """ # did we encounter an error? if type(query.RESPONSE) is DeviceError: code, description, symbol = query.RESPONSE.error() raise ResponseException("device {} raised {}".format( query.RESPONSE.ADDRESS, description)) def _read(self, size): """ Read n=size bytes from serial, if <n bytes are received (serial.read() return because of timeout), raise a timeout. """ recv = self.ser.read(size=size) if len(recv) < size: raise ResponseTimeout("timeout while communication via serial") else: return recv def _execute(self, query): # clear buffers self.ser.reset_output_buffer() self.ser.reset_input_buffer() # send query self.ser.write(query.compose()) # print(query.compose()) # flush write cache self.ser.flush() # initialize response and carriage return cr = "\r".encode() response_frame = b'' response_byte = self._read( size=1 ) # read one byte at a time, timeout is set on instance level # read until stop byte while response_byte != cr: response_frame += response_byte response_byte = self._read(size=1) # strip source byte (! or #, but for a response always !) response_frame = response_frame[1:] # print(response_frame) query.set_response(response_frame) # did we encounter an error? self._raise(query) return query def _get(self, parameter_name=None, parameter_id=None, *args, **kwargs): """ Get a query object for a VR command. :param parameter_name: :param parameter_id: :param args: :param kwargs: :return: """ assert parameter_name is not None or parameter_id is not None # search in DataFrame returns a dict parameter = self._find_parameter(parameter_name, parameter_id) # execute query vr = self._execute( VR(parameter=parameter, sequence=self.SEQUENCE_COUNTER, *args, **kwargs)) # increment sequence counter self._inc() # print(vr.PAYLOAD) # print(vr.RESPONSE.PAYLOAD) # return the query with response return vr def _set(self, value, parameter_name=None, parameter_id=None, *args, **kwargs): """ Get a query object for a VS command. :param value: :param parameter_name: :param parameter_id: :param args: :param kwargs: :return: """ assert parameter_name is not None or parameter_id is not None # search in DataFrame returns a dict parameter = self._find_parameter(parameter_name, parameter_id) # execute query vs = self._execute( VS(value=value, parameter=parameter, sequence=self.SEQUENCE_COUNTER, *args, **kwargs)) # increment sequence counter self._inc() # return the query with response return vs def reset(self, *args, **kwargs): """ Send the RS command to the device. :param args: :param kwargs: :return: """ # execute query rs = self._execute(RS(sequence=self.SEQUENCE_COUNTER, *args, **kwargs)) # increment sequence counter self._inc() # return the query with response return rs def get_parameter(self, parameter_name=None, parameter_id=None, *args, **kwargs): """ Get the value of a parameter given by name or id. Returns a list of success and value. :param parameter_name: :param parameter_id: :param args: :param kwargs: :return: int or float """ # get the query object vr = self._get(parameter_id=parameter_id, parameter_name=parameter_name, *args, **kwargs) return vr.RESPONSE.PAYLOAD[0] def set_parameter(self, value, parameter_name=None, parameter_id=None, *args, **kwargs): """ Set the new value of a parameter given by name or id. Performs an immediate get_parameter to check success. Returns success and new value. :param value: :param parameter_name: :param parameter_id: :param args: :param kwargs: :return: bool """ # get the query object vs = self._set(value=value, parameter_id=parameter_id, parameter_name=parameter_name, *args, **kwargs) # check if value setting has succeeded value_set = self.get_parameter(parameter_id=parameter_id, parameter_name=parameter_name, *args, **kwargs) # return True if the values are equal return value == value_set # returns device address identify = partialmethod(get_parameter, parameter_name="Device Address") """ Returns success and device address as int. """ def status(self, *args, **kwargs): """ Get the device status. Returns success and status as readable str. :param args: :param kwargs: :return: [bool, str] """ # query device status status_id = self.get_parameter(parameter_name="Device Status", *args, **kwargs) if status_id == 0: status_name = "Init" elif status_id == 1: status_name = "Ready" elif status_id == 2: status_name = "Run" elif status_id == 3: status_name = "Error" elif status_id == 4: status_name = "Bootloader" elif status_id == 5: status_name = "Device will Reset within next 200ms" else: status_name = "Unknown" # return address and status return status_name # enable or disable auto saving to flash enable_autosave = partialmethod(set_parameter, value=0, parameter_name="Save Data to Flash") disable_autosave = partialmethod(set_parameter, value=1, parameter_name="Save Data to Flash") def write_to_flash(self, *args, **kwargs): """ Write parameters to flash. :param args: :param kwargs: :return: bool """ self.enable_autosave() timer_start = time.time() # value 0 means "All Parameters are saved to Flash" while self.get_parameter(parameter_name="Flash Status") != 0: # check for timeout if time.time() - timer_start > 10: raise ResponseTimeout("writing to flash timed out!") time.sleep(0.5) self.disable_autosave() return True
class TEC_Serial(TEC): """ Discrete implementation of the TEC class on an USB based interface """ def __init__(self, port, timeout=1, baudrate=57600, tec_address=0, check_crc=True): super().__init__(tec_address=tec_address, check_crc=check_crc) self.port = port self.timeout = timeout self.baudrate = baudrate self.ser = Serial( port=self.port, timeout=self.timeout, baudrate=self.baudrate, ) self.ser.flush() def __exit__(self, exc_type, exc_val, exc_tb): self.ser.__exit__(exc_type, exc_val, exc_tb) def __enter__(self): return self def stop(self): self.ser.flush() self.ser.close() def _send_and_receive(self, frame): byte_arr = frame + b'\r' #clear all remaining buffers self.ser.reset_output_buffer() self.ser.reset_input_buffer() #send and flush self.ser.write(byte_arr) self.ser.flush() #read all in answer_arr = self.ser.read_until(b'\r') return answer_arr[0:-1] def _send_and_ignore_receive(self, frame): byte_arr = frame + b'\r' #clear all remaining buffers self.ser.reset_output_buffer() self.ser.reset_input_buffer() #send and flush self.ser.write(byte_arr) self.ser.flush() #wait for first answer and discard if tec_address is not 255 if self.tec_address != 255: self.ser.read() self.ser.flush() def _speed_changed(self, speed): self.baudrate = speed self.ser.baudrate = speed