Source code for MPDSnCxx_Interface

import sys
import serial as pyserial
from serial.tools.list_ports import comports

[docs] class MPDSnCxx_Interface: def __init__(self, vid, pid, serial): self.VID = vid self.PID = pid self.SERIALNUM = serial self.device_found = False for port in comports(): if self.VID and self.PID and self.SERIALNUM in port.hwid: print("Device found") print("PID: " + str(self.PID)) print("VID: " + str(self.VID)) print("Serial Number: " + str(self.SERIALNUM)) print("Port Name:" + port.name) self.PORT = port.name self.device_found = True break self.BAUDRATE = 9600 # integer self.BYTESIZE = pyserial.EIGHTBITS # possible values are five, six, seven, eight self.PARITY = pyserial.PARITY_NONE # possible values are none, even, odd, mark, space self.STOPBITS = pyserial.STOPBITS_ONE # possible values are one, one_point_five, two self.TIMEOUT = None # float, CAN BE NONE self.XONXOFF = False # boolean self.RTSCTS = False # boolean self.DSRDTR = False # boolean self.WRITE_TIMEOUT = None # float, CAN BE NONE self.INTER_BYTE_TIMEOUT = None # float, CAN BE NONE self.EXCLUSIVE = None # boolean, CAN BE NONE self.num_channels = 0 #check if device is found, if not return if not self.device_found: self.__device_not_found() raise RuntimeError("Device not found") def __del__(self): if self.device_found: self.disconnect_device() def __device_not_found(self): print("\nDevice not found") print("PID: " + str(self.PID)) print("VID: " + str(self.VID)) print("Serial Number: " + str(self.SERIALNUM))
[docs] def connect_device(self, baudrate=9600, bytesize=pyserial.EIGHTBITS, parity=pyserial.PARITY_NONE, stopbits=pyserial.STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False, write_timeout=None, inter_byte_timeout=None, exclusive=None): """ Connect to the MPDSnCxx Interface. Parameters ---------- baudrate : int, optional baudrate, by default 9600 bytesize : _type_, optional bytesize, by default pyserial.EIGHTBITS parity : _type_, optional parity, by default pyserial.PARITY_NONE stopbits : _type_, optional stopbits, by default pyserial.STOPBITS_ONE, timeout : float, optional timeout, by default None xonxoff : bool, optional xonxoff, by default False rtscts : bool, optional rtscts, by default False dsrdtr : bool, optional dsrdtr, by default False write_timeout : float, optional write_timeout, by default None inter_byte_timeout : float, optional inter_byte_timeout, by default None exclusive : boolean, optional exclusive, by default None """ self.BAUDRATE = baudrate # integer self.BYTESIZE = bytesize # possible values are five, six, seven, eight self.PARITY = parity # possible values are none, even, odd, mark, space self.STOPBITS = stopbits # possible values are one, one_point_five, two self.TIMEOUT = timeout # float, CAN BE NONE self.XONXOFF = xonxoff # boolean self.RTSCTS = rtscts # boolean self.DSRDTR = dsrdtr # boolean self.WRITE_TIMEOUT = write_timeout # float, CAN BE NONE self.INTER_BYTE_TIMEOUT = inter_byte_timeout # float, CAN BE NONE self.EXCLUSIVE = exclusive # boolean, CAN BE NONE self.SER = pyserial.Serial(port=self.PORT, baudrate=baudrate, bytesize=bytesize, parity=parity, stopbits=stopbits, timeout=timeout, xonxoff=xonxoff, rtscts=rtscts, dsrdtr=dsrdtr, write_timeout=write_timeout, inter_byte_timeout=inter_byte_timeout, exclusive=exclusive)
[docs] def disconnect_device(self): """Disconnect from the MPDSnCxx Radio Frequency Driver """ self.SER.close() print("\nPort Closed") self.device_found = False
[docs] def print_self(self): """Print to terminal the settings for the USB connection """ print("\nPort:" + str(self.PORT)) print("Baudrate: "+ str(self.BAUDRATE)) print("Bytesize: "+ str(self.BYTESIZE)) print("Parity: "+ str(self.PARITY)) print("Stopbits: "+ str(self.STOPBITS)) print("Timeout: "+ str(self.TIMEOUT)) print("XONXOFF: "+ str(self.XONXOFF)) print("RTSCTS: "+ str(self.RTSCTS)) print("DSRDT: "+ str(self.DSRDTR)) print("Inter Byte Timeout: "+ str(self.INTER_BYTE_TIMEOUT)) print("Write Timeout: "+ str(self.WRITE_TIMEOUT)) print("Exclusive: "+ str(self.EXCLUSIVE))
[docs] def create_fast_command(self, channel=None, frequency=None, powerP=None, powerD=None, switch=None, internal=None, store=None): """Create formatted quick command to set the MPDSnCxx Radio Frequency Driver in normal mode \n FULL Command: LxFfff.ffPppppDdd.ddOoIiE Parameters ---------- channel : int, Channel selection (x= 1 to 8 for channels, 0 for BLK selection[Oo, Ii, only] ) frequency : float, optional Frequency adjustment (fff.ff = frequency value ex-142.26 - MHz, by default None powerP : int, optional Power adjustment (pppp = 0 to 1023), by default None powerD : float, optional Power adjustment (dBm, ex dd.dd=17.45), by default None switch : int, optional Switch ON/OFF (o=1/0), by default None internal : int, optional Internal mode ON/OFF (i=1/0), by default None store : int, optional Immediate store, by default None Returns ------- String normal operation command to be sent to MPDSnCxx Radio Frequency Driver """ command = "L" if channel is None: raise Exception("The channel parameter must be set.") if not(isinstance(channel, int)): raise Exception(f"The channel parameter must be an integer. ({channel=})") if (channel > self.num_channels or channel < 0): raise Exception(f"The channel parameter must be between 0 and {self.num_channels} inclusive. ({channel=})") command = command+str(channel) if ((frequency is not None) and channel !=0): if not(isinstance(frequency,float)): raise Exception(f"The frequency parameter must be a float. ({frequency=})") freq = f"F{frequency:07.3f}" command = command + freq if ((powerP is not None) and (powerD is not None)): raise Exception(f"Both powerP and powerD cannot be set. ({powerP=}, {powerD=})") if ((powerP is not None) and channel !=0): if not(isinstance(powerP,int)): raise Exception(f"The powerP parameter must be an integer. ({powerP=})") if (powerP>=0 and powerP<=1023): power = f"P{powerP:04d}" command = command + power else: raise Exception(f"powerP must be in the range of 0-1023 inclusive. ({powerP=})") if ((powerD is not None) and channel !=0): if not(isinstance(powerD,float)): raise Exception(f"The powerD parameter must be a float. ({powerD=})") power = f"D{powerD:05.2f}" command = command + power if switch is not None: if not(isinstance(switch,int)): raise Exception("Switch must be of type integer") if switch == 0 or switch == 1: command = command + "O" +str(switch) else: raise Exception(f"Switch must be 0 or 1({switch=})") if internal is not None: if not(isinstance(internal,int)): raise Exception("Internal must be of type integer") if internal == 0 or internal == 1: command = command + "I" + str(internal) else: raise Exception(f"Internal must be 0 or 1({internal=})") if ((store is not None) and channel != 0): if isinstance(store,bool): if store: command = command + "E" else: raise Exception("Store parameter must be type of boolean") return command
[docs] def create_sweeping_command(self, sweeping = None, frequency_start=None, frequency_stop=None, sweeping_time=None, store=None): """Create formatted quick command to set the MPDSnCxx Radio Frequency Driver in sweeping mode \n FULL Command: GgAfff.fffOfff.fffUuuuuE (applies on channel 1 only) Parameters ---------- sweeping : int Sweeping mode - OFF/ON - g=0/1, by default None frequencyStart : float, optional Start frequency (fff.ff = frequency value ex-75.206 – MHz), by default None frequencyStop : float, optional Stop frequency (fff.ff = frequency value ex-84.260 – MHz), by default None SweepingTime : int, optional Sweeping time in microseconds by steps of 1μs from 1 to 5000, by default None store : bool, optional Immediate store, by default None Returns ------- String sweeping command to be sent to MPDSnCxx Radio Frequency Driver """ command = "G" if sweeping is None: raise Exception("The sweeping parameter must be set.") if not(isinstance(sweeping,int)): raise Exception(f"The sweeping parameter must be an integer. ({sweeping=})") if (sweeping == 0 or sweeping == 1): command = command+str(sweeping) else: raise Exception(f"The sweeping parameter must be 0 or 1. ({sweeping=})") if (frequency_start is not None): if not(isinstance(frequency_start,float)): raise Exception(f"The frequencyStart parameter must be a float. ({frequency_start=})") freqstart = f"A{frequency_start:07.3f}" command = command + freqstart if (frequency_stop is not None): if not(isinstance(frequency_stop,float)): raise Exception(f"The frequencyStop parameter must be a float. ({frequency_stop=})") freqstop = f"O{frequency_stop:07.3f}" command = command + freqstop if (sweeping_time is not None): if not(isinstance(sweeping_time,int)): raise Exception(f"The SweepingTime parameter must be an integer. ({sweeping_time=})") if (sweeping_time>=1 and sweeping_time<=5000): time = f"U{sweeping_time:04d}" command = command + time else: raise Exception(f"SweepingTime must be in the range of 1-5000 inclusive. ({sweeping_time=})") if (store is not None): if isinstance(store,bool): if store: command = command + "E" else: raise Exception("Store parameter must be type of boolean") return command
def __write_to_device(self, command): command = command + "\n\r" self.SER.write(command.encode())
[docs] def read_status(self, long_form=False): """Read the status of MPDSnCxx Radio Frequency Driver Parameters ---------- long_form : bool Display all the status, by default False """ self.__write_to_device("S") self.SER.read_until("\n\r".encode()) line = self.SER.read_until("\n\r".encode()) count = 0 num_chan_set = False bPassed = False print("Status:\n", end = " ") while line != b"": if not bPassed: print(line) elif long_form: print(line) count += 1 if b"?" in line: bPassed = True if not num_chan_set: self.num_channels = count - 2 num_chan_set = True self.__write_to_device("") line = self.SER.read_until("\n\r".encode()) print("") if (not num_chan_set): self.num_channels = count - 3
[docs] def send_quick_command(self, command): """Sends a command to MPDSnCxx Radio Frequency Driver Parameters ---------- command : String Formated command to be sent """ command = command + "\n\r" self.SER.write(command.encode()) self.SER.read_until("\n\r".encode())