diff --git a/ProberControl/config/ProberConfig.conf b/ProberControl/config/ProberConfig.conf
index 8b13789..d415eab 100644
--- a/ProberControl/config/ProberConfig.conf
+++ b/ProberControl/config/ProberConfig.conf
@@ -1 +1,41 @@
+## Object Type
+M
+#O Model
+TL2500
+#Address
+179.29.100.100::12345
+##
+## Object Type
+M
+#O Model
+Keysight8164B_Laser
+#Address
+GPIB0::20::INSTR
+##
+
+## Object Type
+M
+#O Model
+Keysight8164B_PowerMeter
+#Address
+GPIB0::20::INSTR
+#Numbering of Channels
+1:1;2:2
+##
+
+## Object Type
+#M
+#O Model
+#EXFOT100HP_Laser
+#Address
+#GPIB0::2::INSTR
+##
+
+## Object Type
+M
+#O Model
+EXFOT100_Laser
+#Address
+GPIB0::3::INSTR
+##
diff --git a/ProberControl/laserSweep1.txt b/ProberControl/laserSweep1.txt
new file mode 100644
index 0000000..6cd4d6a
--- /dev/null
+++ b/ProberControl/laserSweep1.txt
@@ -0,0 +1,36 @@
+##get_o_spectrum_0:
+1501.0 -43.2760465352
+
+
+##get_o_spectrum_0:
+1509.0 -36.4708130008
+
+##get_o_spectrum_1:
+1500.0 0.242220526355
+1501.0 0.25293050514
+1502.0 0.25293050514
+1503.0 0.25293050514
+1504.0 0.254458484579
+1505.0 0.251402465073
+1506.0 0.254458484579
+1507.0 0.260564555962
+1508.0 0.261327271114
+1509.0 0.265138363286
+
+
+##get_o_spectrum_0:
+1509.0 -36.4708130008
+
+##get_o_spectrum_1:
+1500.0 0.242220526355
+1501.0 0.25293050514
+1502.0 0.25293050514
+1503.0 0.25293050514
+1504.0 0.254458484579
+1505.0 0.251402465073
+1506.0 0.254458484579
+1507.0 0.260564555962
+1508.0 0.261327271114
+1509.0 0.265138363286
+
+
diff --git a/ProberControl/prober/instruments/EXFOT100HP_Laser.py b/ProberControl/prober/instruments/EXFOT100HP_Laser.py
new file mode 100644
index 0000000..2f6ae01
--- /dev/null
+++ b/ProberControl/prober/instruments/EXFOT100HP_Laser.py
@@ -0,0 +1,267 @@
+import time
+import visa
+
+class EXFOT100HP_Laser(object):
+ '''
+ This class models the EXFO T100S-HP laser. There is a
+ 1260-1360 nm and a 1500-1630 nm version.
+
+ .. note:: When using any laser command, remember to send shut-off-laser command at the end of each sweep command set.
+ For Trigger Sweep, send shut-off-laser command after sweep ends (sweep end condition noted in TriggerSweepSetup function)
+ Note that these lasers do not have trigger inputs or outputs.
+ '''
+
+ def __init__(self, res_manager, address='GPIB0::2::INSTR'):
+ '''
+ Constructor method
+
+ :param res_manager: PyVisa resource manager
+ :type res_manager: PyVisa resourceManager object
+ :param address: SCPI address of instrument
+ :type address: string
+ '''
+
+ self.active = False
+
+ self.gpib = res_manager.open_resource(address)
+
+ self.gpib.write ('*IDN?')
+ info = self.gpib.read()
+ print ('Connection Successful: %s' % info)
+
+ #Ensure Output is OFF
+ self.gpib.write ('DISABLE')
+
+ #Default Laser Power Unit to dBm
+ self.gpib.write ('DBM')
+
+ #Set system operation to constant power models
+ self.gpib.write ('APCON')
+
+ #Get min and max wavelengths
+ self.get_min_wavelength()
+ self.get_max_wavelength()
+
+ def whoAmI(self):
+ ''':returns: reference to device'''
+ return 'Laser'
+
+ def change_state(self):
+
+ if self.active == True:
+ self.active = False
+ else:
+ self.active = True
+ print 'state = ', self.active
+
+ def get_max_wavelength(self): # Updated 9/20/2019 Jim Davis
+ '''
+ Queries the maximum allowed wavelength
+
+ :returns: Float
+ '''
+ self.gpib.write ('L? MAX')
+
+ self.max_wavelength = float(self.gpib.read()[2:])
+ print 'Wavelength Max: ', self.max_wavelength, 'nm'
+ return self.max_wavelength
+
+ def get_min_wavelength(self): # Updated 9/20/2019 Jim Davis
+ '''
+ Queries the minimum allowed wavelength
+
+ :returns: Float
+ '''
+ self.gpib.write ('L? MIN')
+ self.min_wavelength = float(self.gpib.read()[2:])
+ print 'Wavelength Min: ', self.min_wavelength, 'nm'
+ return self.min_wavelength
+
+ def setwavelength(self, wavelength):
+ '''
+ Loads a single wavelength and sets output on
+
+ :param waveLength: Specified wavelength
+ :type waveLength: Integer
+ '''
+ self.outputOFF()
+
+ if wavelength < self.min_wavelength or wavelength > self.max_wavelength:
+ print ('Specified Wavelength Out of Range: ' +str(wavelength))
+ else :
+ # Execute setting of wavelength
+ self.gpib.write('L = ' + str(wavelength))
+ print(str(wavelength))
+ time.sleep(0.55)
+ self.gpib.write('L?')
+ info = self.gpib.read()
+ print ('Wavelength Sent: %s' % info)
+
+ #self.gpib.write('SOURCE0:CHAN1:POW:STATE 1')
+ self.outputON()
+
+
+ def sweepWavelengthsContinuous (self, start, end, power):
+ '''
+ Executes a continuous sweep, not for use with triggered PowerMeters
+
+ :param start: Specified wavelength between 1260-1360 nm, or 1500-1630 nm
+ :type start: Float
+ :param end: Specified wavelength between 1260-1360 nm, or 1500-1630 nm
+ :type end: Float
+ :param power: Specified power for sweep
+ :type power: Float
+ :Note: motor_speed is calculated from end - start to be < 2 seconds
+ :to avoid a timeout from PyVisa before laser scan completes
+ '''
+
+ self.outputOFF()
+
+ # time to wait before checking OPC = operation complete bit
+ sleepTime = 0.01
+
+ # Calcualte motor speed to key scan time < 2 s
+ wavelength_span = (end - start)
+ max_scan_time = 2.0 #s
+ #reverse ordered to make search easy
+ motor_speed_list = [100,67,50,40,33,29,25,22,20,18,17,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]
+ for x in motor_speed_list:
+ scan_time = wavelength_span /x
+ if scan_time < max_scan_time:
+ new_scan_time = scan_time
+ print ' new_scan_time',new_scan_time
+ print 'speed = ',
+ motor_speed = wavelength_span / new_scan_time
+ print 'scan motor_speed = ', motor_speed
+ print 'scan_time = ', new_scan_time
+
+ if (start < self.min_wavelength
+ or start > self.max_wavelength
+ or end < self.min_wavelength
+ or end > self.max_wavelength
+ or end <= start):
+ print ('Specified Wavelengths Out of Range')
+
+ else:
+ while not self.checkOPC():
+ time.sleep(sleepTime)
+ else:
+ self.setpower(power)
+
+ while not self.checkOPC():
+ time.sleep(sleepTime)
+ else:
+ self.setwavelength(start)
+
+ while not self.checkOPC():
+ time.sleep(sleepTime)
+ else:
+ self.gpib.write('MOTOR_SPEED ' +str(motor_speed))
+
+ while not self.checkOPC():
+ time.sleep(sleepTime)
+ else:
+ self.gpib.write('ACTCTRLON')
+
+ while not self.checkOPC():
+ time.sleep(sleepTime)
+ else:
+ self.setwavelength(end)
+ print 'setwavelength(end)'
+
+ # maximum motor speed to return
+ while not self.checkOPC():
+ print 'INSIDE not self.checkOPC'
+ time.sleep(sleepTime)
+ else:
+ self.gpib.write('MOTOR_SPEED = ' + '100')
+ self.gpib.write('MOTOR_SPEED?')
+ print 'MOTOR_SPEED = ', self.gpib.read()
+
+ while not self.checkOPC():
+ time.sleep(sleepTime)
+ else:
+ self.gpib.write('ACTCTRLOFF')
+
+ def checkOPC(self):
+ # check OPC bit of STB status bit. Mask out other bits with &
+ return (int(self.gpib.write ('*STB?')[0] & 1))
+
+ def outputON(self):
+ '''
+ Turns output of laser source ON
+ '''
+ self.gpib.write('ENABLE')
+
+ def outputOFF(self):
+ '''
+ Turns output of laser source OFF
+
+ '''
+ self.gpib.write('DISABLE')
+
+ def getwavelength(self):
+ '''
+ Queries wavelength of the laser
+
+ :returns: Float
+ '''
+ self.gpib.write('L?')
+ return float(self.gpib.read()[2:])
+
+ def setpower(self, power = 0.0 ):
+ '''
+ Sets power in dbm
+
+ :param power: Specified power to set the laser to in dbm
+ :type power: Float
+ '''
+ power = float(power)
+ if (power < -6.99) or (power > 13.4):
+ print 'Power setting out of -6.99 to +13.4 dBm range'
+ else:
+ self.gpib.write('P = ' + str(power))
+
+ def getpower(self):
+ '''
+ Gets output power in dbm
+
+ :returns: Float
+ '''
+ self.gpib.write('P?')
+ self.power = self.gpib.read()
+ print 'power read as: ', type(self.power), self.power
+ if self.power[0:2] == 'P=':
+ print 'Laser ENABLED'
+ self.power = float(self.power[2:])
+ else:
+ print 'Laser DISABLED'
+ self.power = 'DISABLED'
+
+ return self.power
+
+ def close(self):
+ '''
+ Release resources
+ '''
+ self.outputOFF()
+ self.gpib.close()
+
+
+#if __name__ == "__main__":
+
+'''
+Copyright (C) 2017 Robert Polster
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
diff --git a/ProberControl/prober/instruments/EXFOT100_Laser.py b/ProberControl/prober/instruments/EXFOT100_Laser.py
new file mode 100644
index 0000000..17f7f8e
--- /dev/null
+++ b/ProberControl/prober/instruments/EXFOT100_Laser.py
@@ -0,0 +1,225 @@
+import time
+import visa
+
+class EXFOT100_Laser(object):
+ '''
+ This class models the EXFO T100S-HP laser. There is a
+ 1260-1360 nm and a 1500-1630 nm version.
+
+ .. note:: When using any laser command, remember to send shut-off-laser command at the end of each sweep command set.
+ For Trigger Sweep, send shut-off-laser command after sweep ends (sweep end condition noted in TriggerSweepSetup function)
+ Note that these lasers do not have trigger inputs or outputs.
+ '''
+
+ def __init__(self, res_manager, address='GPIB0::3::INSTR'):
+ '''
+ Constructor method
+
+ :param res_manager: PyVisa resource manager
+ :type res_manager: PyVisa resourceManager object
+ :param address: SCPI address of instrument
+ :type address: string
+ '''
+
+ self.active = False
+
+ self.gpib = res_manager.open_resource(address)
+
+ self.gpib.write ('*IDN?')
+ info = self.gpib.read()
+ print ('Connection Successful: %s' % info)
+
+ #Ensure Output is OFF
+ self.gpib.write ('DISABLE')
+
+ #Default Laser Power Unit to dBm
+ self.gpib.write ('DBM')
+
+ #Default Spectral Unit Selection
+ self.gpib.write('NM')
+
+ #Get min and max wavelengths
+ #self.get_min_wavelength()
+ #self.get_max_wavelength()
+
+ def whoAmI(self):
+ ''':returns: reference to device'''
+ return 'Laser'
+
+ def change_state(self):
+
+ if self.active == True:
+ self.active = False
+ else:
+ self.active = True
+ print 'state = ', self.active
+
+ def chan_enable(self, channel):
+ print 'Enable CH' + str(int(channel)) +':ENABLE'
+ self.gpib.write('CH' + str(int(channel)) +':ENABLE')
+
+ def chan_disable(self, channel):
+ print 'Disable CH' + str(int(channel)) +':DISABLE'
+ self.gpib.write('CH' + str(int(channel)) +':DISABLE')
+
+ def All_chan_enable(self):
+ #Disable the laser output on allinstalled OCICS modules
+ self.gpib.write('ENABLE')
+
+ def All_chan_disable(self):
+ #Enable the laser output on allinstalled OCICS modules
+ self.gpib.write('DISABLE')
+
+
+ def get_type(self, channel): # Updated 11/5/2019 Jim Davis
+ '''
+ Queries the channel type
+
+ :returns: String
+ '''
+ if (channel == 1) or (channel == 2):
+ self.gpib.write ('CH' + str(int(channel)) +':TYPE?')
+ self.type = str(self.gpib.read())
+ else:
+ print 'Channel not yet implemented in driver'
+ self.type = ''
+
+ return self.type
+
+ def setwavelength(self, channel, wavelength):
+ '''
+ Loads a single wavelength and channel
+ Sets output wavelength
+
+ :param waveLength: Specified wavelength
+ type channel: int
+ :type waveLength: Float
+ '''
+ wavelength = float(wavelength)
+ if channel == 1:
+ if (wavelength < 1260.0) or (wavelength > 1360.0):
+ print 'Channel 1 Wavelength setting out of 1260.0 - 1360.0 nm range'
+ else:
+ self.chan_enable(channel) # Errors if channel not enabled
+ self.gpib.write('CH' + str(int(channel)) + ':L = ' + str(wavelength))
+ elif channel == 2:
+ if (wavelength < 1520.0) or (wavelength > 1630.0):
+ print 'Channel 2 Wavelength setting out of 1520.0 - 1630.0 range'
+ else:
+ self.chan_enable(channel) # Errors if channel not enabled
+ self.gpib.write('CH' + str(int(channel)) + ':L = ' + str(wavelength))
+ else:
+ print 'Channel not yet implemented in driver'
+
+ def checkOPC(self):
+ # check OPC bit of STB status bit. Mask out other bits with &
+ return (int(self.gpib.write ('*STB?')[0] & 1))
+
+ def getwavelength(self, channel):
+ '''
+ Queries wavelength of the laser
+ Checks wavelength by channel
+
+ :returns: float
+ '''
+ if (channel == 1) or (channel == 2):
+ self.gpib.write('CH' + str(int(channel)) + ':L?')
+ return float(self.gpib.read()[6:])
+ else:
+ print 'Channel not yet implemented in driver'
+ return ''
+
+ def setpower(self, channel, power = 0.0 ):
+ '''
+ Sets power in dbm for channels implement in driver
+ Checks range for each laser
+
+ :param power: Specified power to set the laser to in dbm
+ :type power: Float
+ '''
+ power = float(power)
+ if channel == 1:
+ if (power < -6.9) or (power > 11.6):
+ print 'Channel 1 Power setting out of -6.9 to +11.6 dBm range'
+ else:
+ self.gpib.write('CH' + str(int(channel)) +':ENABLE')
+ self.gpib.write('CH' + str(int(channel)) + ':P = ' + str(power))
+ elif channel == 2:
+ if (power < -6.9) or (power > 7.8):
+ print 'Channel 2 Power setting out of -6.9 to +7.8 dBm range'
+ else:
+ self.gpib.write('CH' + str(int(channel)) +':ENABLE')
+ self.gpib.write('CH' + str(int(channel)) + ':P = ' + str(power))
+ else:
+ print 'Channel not yet implemented in driver'
+
+
+
+ def getpower(self, channel):
+ '''
+ Gets output power in dbm
+
+ :returns: Float
+ '''
+
+ if (channel == 1) or (channel == 2):
+ self.gpib.write('CH' + str(int(channel)) + ':P?')
+ self.power = self.gpib.read()
+ return self.power
+ else:
+ print 'Channel not yet implemented in driver'
+ self.power = ''
+ return self.power
+
+ def Coherence_ctrl (self, channel, ctrl):
+ '''
+ Sets coherence control on for ctrl = 1, off for ctrl = 0
+ Returns 0 for Coherence control OFF, 1 for Coherence control ON
+ '''
+
+ if (channel == 1) or (channel == 2):
+ if (ctrl == 0):
+
+ self.gpib.write('CH' + str(int(channel)) + ':CTRL OFF')
+ self.gpib.write('CH' + str(int(channel)) + ':CTRL?')
+ Coherence = self.gpib.read()
+ print 'CH', str(int(channel)), ':CTRL OFF'
+ return Coherence[4]
+ #print self.gpib.read()[4]
+ elif (ctrl == 1):
+ self.gpib.write('CH' + str(int(channel)) + ':CTRL ON')
+ self.gpib.write('CH' + str(int(channel)) + ':CTRL?')
+ Coherence = self.gpib.read()
+ print 'CH', str(int(channel)), ':CTRL ON'
+ return Coherence[4]
+ else:
+ print 'Error in ctrl: ON: ctrl=1, OFF: ctrl=0'
+
+ else:
+ print 'Channel not yet implemented in driver'
+ return ''
+
+ def close(self):
+ '''
+ Release resources
+ '''
+ self.All_chan_disable()
+ self.gpib.close()
+
+#if __name__ == "__main__":
+
+'''
+Copyright (C) 2017 Robert Polster
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
diff --git a/ProberControl/prober/instruments/GenPhotPCD104.py b/ProberControl/prober/instruments/GenPhotPCD104.py
new file mode 100644
index 0000000..7762f9d
--- /dev/null
+++ b/ProberControl/prober/instruments/GenPhotPCD104.py
@@ -0,0 +1,79 @@
+import time
+import visa
+
+class GenPhotPCD104(object):
+ '''
+ This class models the General Photonics Polarization Scrambler
+
+ .. note:: When using any laser command, remember to send shut-off-laser command at the end of each sweep command set.
+ For Trigger Sweep, send shut-off-laser command after sweep ends (sweep end condition noted in TriggerSweepSetup function)
+ '''
+
+ def __init__(self, res_manager, address='GPIB0::5::INSTR'):
+ '''
+ Constructor method
+
+ :param res_manager: PyVisa resource manager
+ :type res_manager: PyVisa resourceManager object
+ :param address: SCPI address of instrument
+ :type address: string
+ '''
+ self.active = False
+ self.gpib = res_manager.open_resource(address)
+ self.gpib.write ('*IDN?')
+ info = self.gpib.read()
+ print ('Connection Successful: %s' % info)
+
+ def whoAmI(self):
+ ''':returns: reference to device'''
+ return 'PolScramb'
+
+ def change_state(self):
+
+ if self.active == True:
+ self.active = False
+ else:
+ self.active = True
+
+ def getWavelength(self):
+ '''Get current Wavelength'''
+ self.gpib.write('*WAV?')
+ info = self.gpib.read()
+ return info
+
+ def enable(self):
+ '''Enable Scrambling'''
+ self.gpib.write('*ENA#')
+
+ def disable(self):
+ '''Disable Scrambling'''
+ self.gpib.write('*DIS#')
+
+ def setWavelength(self, wavelength):
+ '''
+ Set Wavelength of Operation
+ '''
+ if wavelength != 980 and wavelength != 1060 and wavelength != 1310 and wavelength != 1480 and wavelength != 1550 and wavelength != 1600:
+ return "Invalid wavelength. Please try again."
+ else:
+ self.gpib.write('*WAV ' + str(int(wavelength))+ '#')
+ return "Success"
+
+
+#if __name__ == "__main__":
+
+'''
+Copyright (C) 2017 Robert Polster
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
diff --git a/ProberControl/prober/instruments/Keysight8164B_Laser - Copy.py b/ProberControl/prober/instruments/Keysight8164B_Laser - Copy.py
new file mode 100644
index 0000000..b4bb9aa
--- /dev/null
+++ b/ProberControl/prober/instruments/Keysight8164B_Laser - Copy.py
@@ -0,0 +1,412 @@
+import time
+import visa
+
+class Keysight8164B_Laser(object):
+ '''
+ This class models the a Keysight 8164A/B Lightwave Multimeter. It controls
+ the Keysight 81608A Laser.
+
+ .. note:: When using any laser command, remember to send shut-off-laser command at the end of each sweep command set.
+ For Trigger Sweep, send shut-off-laser command after sweep ends (sweep end condition noted in TriggerSweepSetup function)
+ '''
+
+ def __init__(self, res_manager, address='GPIB0::1::INSTR'):
+ '''
+ Constructor method
+
+ :param res_manager: PyVisa resource manager
+ :type res_manager: PyVisa resourceManager object
+ :param address: SCPI address of instrument
+ :type address: string
+ '''
+
+ self.active = False
+
+ self.gpib = res_manager.open_resource(address)
+ self.gpib.write('LOCK 0, 1234')
+
+ self.gpib.write ('*IDN?')
+ info = self.gpib.read()
+ print ('Connection Successful: %s' % info)
+
+ self.gpib.write ('LOCK?')
+ info = self.gpib.read()
+ print('Locked: %s' %info)
+
+ #Ensure Output is OFF
+ self.gpib.write ('SOURCE0:CHAN1:POW:STATE 0')
+
+ #Default Laser Power Unit to dBm
+ self.gpib.write ('SOURCE0:CHAN1:POW:UNIT 0')
+
+ #Enables Display
+ self.gpib.write ('DISP:ENAB 1')
+
+ #Check Output Status
+ time.sleep(0.55)
+ self.gpib.write ('SOURCE0:CHAN1:POW:STATE?')
+ info = self.gpib.read()
+ print('Output: %s' %info)
+
+
+
+ def whoAmI(self):
+ ''':returns: reference to device'''
+ return 'Laser'
+
+ def change_state(self):
+
+ if self.active == True:
+ self.active = False
+ else:
+ self.active = True
+ print 'state = ', self.active
+
+ def get_max_wavelength(self): # Updated 9/20/2019 Jim Davis
+ '''
+ Queries the maximum allowed wavelength
+
+ :returns: Integer
+ '''
+ self.gpib.write ('SOURCE0:CHAN1:WAV? MAX')
+ max_wavelength = self.gpib.read()
+ self.max_wavelength = int(float(max_wavelength) * 1E9) - 1 # correct for 1 nm error
+ #print 'Wavelength Max: ', self.max_wavelength, 'nm'
+ return self.max_wavelength
+
+ def get_min_wavelength(self): # Updated 9/20/2019 Jim Davis
+ '''
+ Queries the minimum allowed wavelength
+
+ :returns: Integer
+ '''
+ self.gpib.write ('SOURCE0:CHAN1:WAV? MIN')
+ min_wavelength = self.gpib.read()
+ self.min_wavelength = int(float(min_wavelength) * 1E9) + 1 # correct for 1 nm error
+ #print 'Wavelength Min: ', self.min_wavelength, 'nm'
+ return self.min_wavelength
+
+ def setwavelength(self, wavelength):
+ '''
+ Loads a single wavelength and sets output high
+
+ :param waveLength: Specified wavelength
+ :type waveLength: Integer
+ '''
+ self.outputOFF()
+
+ if wavelength < self.min_wavelength or wavelength > self.max_wavelength:
+ print ('Specified Wavelength Out of Range: ' +str(wavelength))
+ else :
+ # Execute setting of wavelength
+ self.gpib.write('SOURCE0:CHAN1:WAV ' + str(wavelength)+ "nm")
+ print(str(wavelength))
+ time.sleep(0.55)
+ self.gpib.write('SOURCE0:CHAN1:WAV?')
+ info = self.gpib.read()
+ print ('Wavelength Sent: %s' % info)
+
+ #self.gpib.write('SOURCE0:CHAN1:POW:STATE 1')
+ self.outputON()
+
+ #High for test period
+ while self.checkStatusSingle() == False:
+ time.sleep(0.2)
+ # Print if successful
+ print('Single Wavelength Complete')
+
+
+ def sweepWavelengthsContinuousTriggerOut (self, start, end, step, speed = 1):
+ '''
+ Executes a sweep, for use with triggered PowerMeters
+
+ :param start: Specified wavelength between 1520-1580
+ :type start: Integer
+ :param end: Specified wavelength between 1520-1580
+ :type end: Integer
+ :param speed: Specified nm/s
+ :type time: Float
+ '''
+
+ self.outputOFF()
+
+ if start < self.min_wavelength or start > self.max_wavelength or end < self.min_wavelength or end > self.max_wavelength:
+ print ('Specified Wavelengths Out of Range')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE CONT')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SPE ' + str(speed) + 'NM/S')
+
+
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:LLOG 0') #Start Logging
+ self.gpib.write('TRIG0:CHAN1:OUTP STF') #Trigger on
+ self.gpib.write('SOURCE0:CHAN1:AM:STAT OFF') #Disabled Amplitude Modulation
+
+ info = int(self.numberOfTriggers())
+ print ('Number of Triggers %s' % info)
+
+ self.outputON()
+
+ def sweepWavelengthsContinuous (self, start, end, step, speed = 1):
+ '''
+ Executes a sweep with respect to a specified time
+
+ :param start: Specified wavelength between 1520-1580
+ :type start: Integer
+ :param end: Specified wavelength between 1520-1580
+ :type end: Integer
+ :param speed: Specified nm/s
+ :type time: Float
+ '''
+
+ self.outputOFF()
+ self.stopSweep()
+
+ if start < self.min_wavelength or start > self.max_wavelength or end < self.min_wavelength or end > self.max_wavelength:
+ print ('Specified Wavelengths Out of Range')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE CONT')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SPE ' + str(speed) + 'NM/S')
+ self.outputON()
+
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR?')
+ start_1 = self.gpib.read()
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP?')
+ end_1 = self.gpib.read()
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SPE?')
+ spe_1 = self.gpib.read()
+
+ print ('Sweep Parameters: %s %s %s' % (start_1, end_1, spe_1))
+
+ self.startSweep() #Single Sweep
+
+ while self.checkSweepStatus() == False:
+ pass
+ print ('Sweep Wavelength Continuous Complete')
+ self.outputOFF()
+
+ def sweepWavelengthsStep (self, start, end, step, dwell):
+ '''
+ Have to keep track of Triggers in main command, use Stop Sweep Command to end sweep.
+ Extra triggers do not make the laser sweep outside of specified end wavelength.
+ Remeber to shut off laser after sweep ends
+
+ :param start: Specified wavelength between 1520-1580
+ :type start: Integer
+ :param end: Specified wavelength between 1520-1580
+ :type end: Integer
+ :param time: Specified time
+ :type time: Float
+ '''
+
+ self.outputOFF()
+ self.stopSweep()
+
+ if (
+ float(start) < self.min_wavelength or
+ float(start) > self.max_wavelength or
+ float(end) < self.min_wavelength or
+ float(end) > self.max_wavelength or
+ float(step) < 0.001
+ ):
+ print ('Specified Wavelengths Out of Range, or Step Too Low')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE:STEP')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:DWEL ' + str(dwell) + 'MS')
+ self.outputON();
+ self.startSweep(); #Single Sweep
+ print ('Stepped Sweep Started')
+ while self.checkSweepStatus() == False:
+ pass
+ print ('Sweep Wavelengths Step Complete')
+ self.outputOFF()
+
+ def numberOfTriggers (self):
+ '''Number of Triggers for Sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:EXP?')
+ info = self.gpib.read()
+ print info
+ return info
+
+ def trigger(self):
+ '''Software Triggers laser'''
+
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SOFT')
+
+ def step(self):
+ '''Manual Step laser'''
+
+ time.sleep(0.4)
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP:NEXT')
+ time.sleep(0.05)
+
+ def checkSweepStatus(self):
+ '''
+ Checks the status of the laser. Handles timeout exception
+
+ :returns: Boolean
+ '''
+
+ try:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE?')
+ status = int (self.gpib.read())
+ #self.gpib.write('SOURCE0:CHAN1:WAV:SWE:FLAG?')
+ #print int(self.gpib.read())
+ print('.'),
+ if status == 0:
+ return True
+ else:
+ return False
+ except Exception:
+ time.sleep(0.2)
+ return self.checkSweepStatus()
+
+
+ def checkStatusSingle(self):
+ '''
+ Checks the status of the laser, just once. Handles timeout exception
+
+ :returns: Boolean
+ '''
+
+ self.gpib.write('*OPC?')
+ status = int(self.gpib.read())
+ if status > 0:
+ return True
+ else:
+ return False
+
+ def sweepWavelengthsManual(self, start, end, step):
+ '''
+ Use if want to manually step by a particular size, in conjuction with Send Single Wavelength
+
+ :param step: specified step increment, but be greater than or equal to 0.001
+ :type step: Float
+ '''
+ self.outputOFF()
+ self.stopSweep()
+
+ if (
+ float(start) < self.min_wavelength or
+ float(start) > self.max_wavelength or
+ float(end) < self.min_wavelength or
+ float(end) > self.max_wavelength or
+ float(step) < 0.001
+ ):
+ print ('Specified Wavelengths Out of Range, or Step Too Low')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE MAN')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.outputON();
+ self.startSweep(); #Single Sweep
+ print ('Manual Setup Complete')
+
+
+ def startSweep(self):
+ '''Start sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE STAR')
+
+ def stopSweep(self):
+ '''Stop sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE STOP')
+
+ def pauseSweep(self):
+ '''Suspend sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE PAUS')
+
+ def resumeSweep(self):
+ '''
+ Use after pause to resume, still have to call trigger() for next data point if using with trigger sweep
+ '''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE CONT')
+
+ def outputON(self):
+ '''
+ Turns output of laser source ON
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW:STATE 1')
+
+ def outputOFF(self):
+ '''
+ Turns output of laser source OFF
+
+ .. note:: Output occasionally doesn't turn off unless turned ON beforehand
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW:STATE 0')
+
+ def getwavelength(self): # 9/23 Change to return nm to match the rest of the functions using nm. Jim Davis
+ '''
+ Queries wavelength of the laser
+
+ :returns: Float
+ '''
+ self.gpib.write('SOURCE0:CHAN1:WAV?')
+ return int(float(self.gpib.read()) * 1.0E9)
+
+ def setpower(self,power = 0 ):
+ '''
+ Sets power in dbm
+
+ :param power: Specified power to set the laser to in dbm
+ :type power: Integer
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW ' + str(power))
+
+ def getpower(self):
+ '''
+ Gets output power in dbm
+
+ :returns: Float
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW?')
+ return float(self.gpib.read())
+
+ def reset(self):
+ '''
+ Release resources
+ '''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:LLOG 0') #Start Logging
+ self.gpib.write('TRIG0:CHAN1:OUTP DIS') #Trigger on
+ self.gpib.write('SOURCE0:CHAN1:AM:STAT OFF') #Disabled Amplitude Modulation
+
+ return 'Laser Reset'
+
+ def close(self):
+ '''
+ Release resources
+ '''
+ self.outputOFF()
+ self.gpib.close()
+
+
+#if __name__ == "__main__":
+
+'''
+Copyright (C) 2017 Robert Polster
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
diff --git a/ProberControl/prober/instruments/Keysight8164B_Laser.py b/ProberControl/prober/instruments/Keysight8164B_Laser.py
new file mode 100644
index 0000000..b4bb9aa
--- /dev/null
+++ b/ProberControl/prober/instruments/Keysight8164B_Laser.py
@@ -0,0 +1,412 @@
+import time
+import visa
+
+class Keysight8164B_Laser(object):
+ '''
+ This class models the a Keysight 8164A/B Lightwave Multimeter. It controls
+ the Keysight 81608A Laser.
+
+ .. note:: When using any laser command, remember to send shut-off-laser command at the end of each sweep command set.
+ For Trigger Sweep, send shut-off-laser command after sweep ends (sweep end condition noted in TriggerSweepSetup function)
+ '''
+
+ def __init__(self, res_manager, address='GPIB0::1::INSTR'):
+ '''
+ Constructor method
+
+ :param res_manager: PyVisa resource manager
+ :type res_manager: PyVisa resourceManager object
+ :param address: SCPI address of instrument
+ :type address: string
+ '''
+
+ self.active = False
+
+ self.gpib = res_manager.open_resource(address)
+ self.gpib.write('LOCK 0, 1234')
+
+ self.gpib.write ('*IDN?')
+ info = self.gpib.read()
+ print ('Connection Successful: %s' % info)
+
+ self.gpib.write ('LOCK?')
+ info = self.gpib.read()
+ print('Locked: %s' %info)
+
+ #Ensure Output is OFF
+ self.gpib.write ('SOURCE0:CHAN1:POW:STATE 0')
+
+ #Default Laser Power Unit to dBm
+ self.gpib.write ('SOURCE0:CHAN1:POW:UNIT 0')
+
+ #Enables Display
+ self.gpib.write ('DISP:ENAB 1')
+
+ #Check Output Status
+ time.sleep(0.55)
+ self.gpib.write ('SOURCE0:CHAN1:POW:STATE?')
+ info = self.gpib.read()
+ print('Output: %s' %info)
+
+
+
+ def whoAmI(self):
+ ''':returns: reference to device'''
+ return 'Laser'
+
+ def change_state(self):
+
+ if self.active == True:
+ self.active = False
+ else:
+ self.active = True
+ print 'state = ', self.active
+
+ def get_max_wavelength(self): # Updated 9/20/2019 Jim Davis
+ '''
+ Queries the maximum allowed wavelength
+
+ :returns: Integer
+ '''
+ self.gpib.write ('SOURCE0:CHAN1:WAV? MAX')
+ max_wavelength = self.gpib.read()
+ self.max_wavelength = int(float(max_wavelength) * 1E9) - 1 # correct for 1 nm error
+ #print 'Wavelength Max: ', self.max_wavelength, 'nm'
+ return self.max_wavelength
+
+ def get_min_wavelength(self): # Updated 9/20/2019 Jim Davis
+ '''
+ Queries the minimum allowed wavelength
+
+ :returns: Integer
+ '''
+ self.gpib.write ('SOURCE0:CHAN1:WAV? MIN')
+ min_wavelength = self.gpib.read()
+ self.min_wavelength = int(float(min_wavelength) * 1E9) + 1 # correct for 1 nm error
+ #print 'Wavelength Min: ', self.min_wavelength, 'nm'
+ return self.min_wavelength
+
+ def setwavelength(self, wavelength):
+ '''
+ Loads a single wavelength and sets output high
+
+ :param waveLength: Specified wavelength
+ :type waveLength: Integer
+ '''
+ self.outputOFF()
+
+ if wavelength < self.min_wavelength or wavelength > self.max_wavelength:
+ print ('Specified Wavelength Out of Range: ' +str(wavelength))
+ else :
+ # Execute setting of wavelength
+ self.gpib.write('SOURCE0:CHAN1:WAV ' + str(wavelength)+ "nm")
+ print(str(wavelength))
+ time.sleep(0.55)
+ self.gpib.write('SOURCE0:CHAN1:WAV?')
+ info = self.gpib.read()
+ print ('Wavelength Sent: %s' % info)
+
+ #self.gpib.write('SOURCE0:CHAN1:POW:STATE 1')
+ self.outputON()
+
+ #High for test period
+ while self.checkStatusSingle() == False:
+ time.sleep(0.2)
+ # Print if successful
+ print('Single Wavelength Complete')
+
+
+ def sweepWavelengthsContinuousTriggerOut (self, start, end, step, speed = 1):
+ '''
+ Executes a sweep, for use with triggered PowerMeters
+
+ :param start: Specified wavelength between 1520-1580
+ :type start: Integer
+ :param end: Specified wavelength between 1520-1580
+ :type end: Integer
+ :param speed: Specified nm/s
+ :type time: Float
+ '''
+
+ self.outputOFF()
+
+ if start < self.min_wavelength or start > self.max_wavelength or end < self.min_wavelength or end > self.max_wavelength:
+ print ('Specified Wavelengths Out of Range')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE CONT')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SPE ' + str(speed) + 'NM/S')
+
+
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:LLOG 0') #Start Logging
+ self.gpib.write('TRIG0:CHAN1:OUTP STF') #Trigger on
+ self.gpib.write('SOURCE0:CHAN1:AM:STAT OFF') #Disabled Amplitude Modulation
+
+ info = int(self.numberOfTriggers())
+ print ('Number of Triggers %s' % info)
+
+ self.outputON()
+
+ def sweepWavelengthsContinuous (self, start, end, step, speed = 1):
+ '''
+ Executes a sweep with respect to a specified time
+
+ :param start: Specified wavelength between 1520-1580
+ :type start: Integer
+ :param end: Specified wavelength between 1520-1580
+ :type end: Integer
+ :param speed: Specified nm/s
+ :type time: Float
+ '''
+
+ self.outputOFF()
+ self.stopSweep()
+
+ if start < self.min_wavelength or start > self.max_wavelength or end < self.min_wavelength or end > self.max_wavelength:
+ print ('Specified Wavelengths Out of Range')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE CONT')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SPE ' + str(speed) + 'NM/S')
+ self.outputON()
+
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR?')
+ start_1 = self.gpib.read()
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP?')
+ end_1 = self.gpib.read()
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SPE?')
+ spe_1 = self.gpib.read()
+
+ print ('Sweep Parameters: %s %s %s' % (start_1, end_1, spe_1))
+
+ self.startSweep() #Single Sweep
+
+ while self.checkSweepStatus() == False:
+ pass
+ print ('Sweep Wavelength Continuous Complete')
+ self.outputOFF()
+
+ def sweepWavelengthsStep (self, start, end, step, dwell):
+ '''
+ Have to keep track of Triggers in main command, use Stop Sweep Command to end sweep.
+ Extra triggers do not make the laser sweep outside of specified end wavelength.
+ Remeber to shut off laser after sweep ends
+
+ :param start: Specified wavelength between 1520-1580
+ :type start: Integer
+ :param end: Specified wavelength between 1520-1580
+ :type end: Integer
+ :param time: Specified time
+ :type time: Float
+ '''
+
+ self.outputOFF()
+ self.stopSweep()
+
+ if (
+ float(start) < self.min_wavelength or
+ float(start) > self.max_wavelength or
+ float(end) < self.min_wavelength or
+ float(end) > self.max_wavelength or
+ float(step) < 0.001
+ ):
+ print ('Specified Wavelengths Out of Range, or Step Too Low')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE:STEP')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:DWEL ' + str(dwell) + 'MS')
+ self.outputON();
+ self.startSweep(); #Single Sweep
+ print ('Stepped Sweep Started')
+ while self.checkSweepStatus() == False:
+ pass
+ print ('Sweep Wavelengths Step Complete')
+ self.outputOFF()
+
+ def numberOfTriggers (self):
+ '''Number of Triggers for Sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:EXP?')
+ info = self.gpib.read()
+ print info
+ return info
+
+ def trigger(self):
+ '''Software Triggers laser'''
+
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:SOFT')
+
+ def step(self):
+ '''Manual Step laser'''
+
+ time.sleep(0.4)
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP:NEXT')
+ time.sleep(0.05)
+
+ def checkSweepStatus(self):
+ '''
+ Checks the status of the laser. Handles timeout exception
+
+ :returns: Boolean
+ '''
+
+ try:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE?')
+ status = int (self.gpib.read())
+ #self.gpib.write('SOURCE0:CHAN1:WAV:SWE:FLAG?')
+ #print int(self.gpib.read())
+ print('.'),
+ if status == 0:
+ return True
+ else:
+ return False
+ except Exception:
+ time.sleep(0.2)
+ return self.checkSweepStatus()
+
+
+ def checkStatusSingle(self):
+ '''
+ Checks the status of the laser, just once. Handles timeout exception
+
+ :returns: Boolean
+ '''
+
+ self.gpib.write('*OPC?')
+ status = int(self.gpib.read())
+ if status > 0:
+ return True
+ else:
+ return False
+
+ def sweepWavelengthsManual(self, start, end, step):
+ '''
+ Use if want to manually step by a particular size, in conjuction with Send Single Wavelength
+
+ :param step: specified step increment, but be greater than or equal to 0.001
+ :type step: Float
+ '''
+ self.outputOFF()
+ self.stopSweep()
+
+ if (
+ float(start) < self.min_wavelength or
+ float(start) > self.max_wavelength or
+ float(end) < self.min_wavelength or
+ float(end) > self.max_wavelength or
+ float(step) < 0.001
+ ):
+ print ('Specified Wavelengths Out of Range, or Step Too Low')
+
+ else:
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:MODE MAN')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STAR ' + str(start) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STOP ' + str(end) + 'NM')
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:STEP ' + str(step) + 'NM')
+ self.outputON();
+ self.startSweep(); #Single Sweep
+ print ('Manual Setup Complete')
+
+
+ def startSweep(self):
+ '''Start sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE STAR')
+
+ def stopSweep(self):
+ '''Stop sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE STOP')
+
+ def pauseSweep(self):
+ '''Suspend sweep'''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE PAUS')
+
+ def resumeSweep(self):
+ '''
+ Use after pause to resume, still have to call trigger() for next data point if using with trigger sweep
+ '''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE CONT')
+
+ def outputON(self):
+ '''
+ Turns output of laser source ON
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW:STATE 1')
+
+ def outputOFF(self):
+ '''
+ Turns output of laser source OFF
+
+ .. note:: Output occasionally doesn't turn off unless turned ON beforehand
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW:STATE 0')
+
+ def getwavelength(self): # 9/23 Change to return nm to match the rest of the functions using nm. Jim Davis
+ '''
+ Queries wavelength of the laser
+
+ :returns: Float
+ '''
+ self.gpib.write('SOURCE0:CHAN1:WAV?')
+ return int(float(self.gpib.read()) * 1.0E9)
+
+ def setpower(self,power = 0 ):
+ '''
+ Sets power in dbm
+
+ :param power: Specified power to set the laser to in dbm
+ :type power: Integer
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW ' + str(power))
+
+ def getpower(self):
+ '''
+ Gets output power in dbm
+
+ :returns: Float
+ '''
+ self.gpib.write('SOURCE0:CHAN1:POW?')
+ return float(self.gpib.read())
+
+ def reset(self):
+ '''
+ Release resources
+ '''
+ self.gpib.write('SOURCE0:CHAN1:WAV:SWE:LLOG 0') #Start Logging
+ self.gpib.write('TRIG0:CHAN1:OUTP DIS') #Trigger on
+ self.gpib.write('SOURCE0:CHAN1:AM:STAT OFF') #Disabled Amplitude Modulation
+
+ return 'Laser Reset'
+
+ def close(self):
+ '''
+ Release resources
+ '''
+ self.outputOFF()
+ self.gpib.close()
+
+
+#if __name__ == "__main__":
+
+'''
+Copyright (C) 2017 Robert Polster
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+'''
diff --git a/ProberControl/prober/instruments/Keysight8164B_PowerMeter - Copy.py b/ProberControl/prober/instruments/Keysight8164B_PowerMeter - Copy.py
new file mode 100644
index 0000000..9a9957e
--- /dev/null
+++ b/ProberControl/prober/instruments/Keysight8164B_PowerMeter - Copy.py
@@ -0,0 +1,165 @@
+#import visa
+#import time
+#import sys
+import struct
+
+class Keysight8164B_PowerMeter(object):
+ '''
+ This class models a Keysight 8164A/B Lightwave Multimeter.
+ It has been tested with the 81630B (High power range of +28dBm)and
+ 81636B (Fast for sweeps)
+ power sensors.
+ '''
+
+ CURRENT_CHANNEL = 1
+
+ def __init__(self,res_manager,address='GPIB0::1::INSTR', channel=1):
+ '''
+ Constructor method
+
+ :param res_manager: PyVisa resource manager
+ :type res_manager: PyVisa resourceManager object
+ :param address: SCPI address of instrument
+ :type address: String
+ '''
+ self.active = False
+ self.gpib = res_manager.open_resource(address)
+ if '.' in str(channel):
+ self.__channel = int(channel.split('.')[0])
+ self.__port = int(channel.split('.')[1])
+ else:
+ self.__channel = channel
+ self.__port = 1
+
+ # Set Power Unit to dbm
+ self.gpib.write('sens' + self.__channel + ':pow:unit 0')
+
+ # Zeros the electrical offsets for a power meter or return loss module [9/20/2019 Jim Davis]
+ self.gpib.write('sens' + self.__channel + ':corr:coll:zero')
+
+ def _checkChannel(self):
+
+ if CURRENT_CHANNEL != self.__channel:
+ _setChannel(self.__channel)
+
+ def _setChannel(self, newChannel):
+ '''
+ The purpose of this method is to change channels
+ The syntax of usage will depend on the particular device.
+ '''
+ CURRENT_CHANNEL = newChannel
+ self.__channel = newChannel
+
+
+ def whoAmI(self):
+
+ ''':returns: reference to device'''
+ print self
+ return 'PowerMeter'
+
+ def get_power(self,wavelength=1550):
+ ''' return power meter reading after setting correct wavelength'''
+ print 'sens',str(int(self.__channel)),':chan',str(int(self.__port)),':pow:wav ',str(wavelength),'nm'
+
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:wav '+str(wavelength)+'nm')
+ return float(self.gpib.query('read'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow?'))
+
+ def get_feedback(self):
+ return self.get_power()
+
+
+ def close(self):
+ '''
+ Release resources
+ '''
+ self.gpib.close()
+
+ def change_state(self):
+
+ if self.active == True:
+ self.active = False
+ else:
+ self.active = True
+
+ def config_meter(self, range = 10):
+ if self.__port != 2:
+ range = int(range)
+
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:unit 0')
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:unit?')
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:range:auto 0') #Auto ranging turned off
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:rang '+str(range)+'DBM')
+ self.gpib.write('trig'+str(int(self.__channel))+':inp:rearm on')
+
+ def prep_measure_on_trigger(self, samples = 64):
+ if self.__port != 2:
+ self.gpib.write('*CLS')
+ samples = int(samples)
+
+ #self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat stab,stop') #switch stab with logg depending
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat logg,stop') #switch stab with logg depending
+ self.gpib.write('trig'+str(int(self.__channel))+':chan'+str(int(self.__port))+':inp sme') #Set up trigger
+ print self.gpib.query('trig'+str(int(self.__channel))+':inp?')
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:par:logg '+str(samples)+',100us')
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:par:logg?')
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat logg,start')
+
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat?')
+ print self.gpib.query('syst:err?')
+
+
+ def get_result_from_log(self,samples=64):
+
+ if self.__port != 2:
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat?')
+
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:res?')
+ data = self.gpib.read_raw()
+ print self.gpib.query('syst:err?')
+
+
+ samples = int(samples)
+
+ #print data
+
+ NofDigits = int(data[1])
+
+ HexData = data[2+NofDigits:2+NofDigits+samples*4]
+
+ FloData = []
+
+ for x in range(0, samples*4-1,4):
+ dat = HexData[x:x+4]
+ val = struct.unpack('.
+'''
diff --git a/ProberControl/prober/instruments/Keysight8164B_PowerMeter.py b/ProberControl/prober/instruments/Keysight8164B_PowerMeter.py
new file mode 100644
index 0000000..9a9957e
--- /dev/null
+++ b/ProberControl/prober/instruments/Keysight8164B_PowerMeter.py
@@ -0,0 +1,165 @@
+#import visa
+#import time
+#import sys
+import struct
+
+class Keysight8164B_PowerMeter(object):
+ '''
+ This class models a Keysight 8164A/B Lightwave Multimeter.
+ It has been tested with the 81630B (High power range of +28dBm)and
+ 81636B (Fast for sweeps)
+ power sensors.
+ '''
+
+ CURRENT_CHANNEL = 1
+
+ def __init__(self,res_manager,address='GPIB0::1::INSTR', channel=1):
+ '''
+ Constructor method
+
+ :param res_manager: PyVisa resource manager
+ :type res_manager: PyVisa resourceManager object
+ :param address: SCPI address of instrument
+ :type address: String
+ '''
+ self.active = False
+ self.gpib = res_manager.open_resource(address)
+ if '.' in str(channel):
+ self.__channel = int(channel.split('.')[0])
+ self.__port = int(channel.split('.')[1])
+ else:
+ self.__channel = channel
+ self.__port = 1
+
+ # Set Power Unit to dbm
+ self.gpib.write('sens' + self.__channel + ':pow:unit 0')
+
+ # Zeros the electrical offsets for a power meter or return loss module [9/20/2019 Jim Davis]
+ self.gpib.write('sens' + self.__channel + ':corr:coll:zero')
+
+ def _checkChannel(self):
+
+ if CURRENT_CHANNEL != self.__channel:
+ _setChannel(self.__channel)
+
+ def _setChannel(self, newChannel):
+ '''
+ The purpose of this method is to change channels
+ The syntax of usage will depend on the particular device.
+ '''
+ CURRENT_CHANNEL = newChannel
+ self.__channel = newChannel
+
+
+ def whoAmI(self):
+
+ ''':returns: reference to device'''
+ print self
+ return 'PowerMeter'
+
+ def get_power(self,wavelength=1550):
+ ''' return power meter reading after setting correct wavelength'''
+ print 'sens',str(int(self.__channel)),':chan',str(int(self.__port)),':pow:wav ',str(wavelength),'nm'
+
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:wav '+str(wavelength)+'nm')
+ return float(self.gpib.query('read'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow?'))
+
+ def get_feedback(self):
+ return self.get_power()
+
+
+ def close(self):
+ '''
+ Release resources
+ '''
+ self.gpib.close()
+
+ def change_state(self):
+
+ if self.active == True:
+ self.active = False
+ else:
+ self.active = True
+
+ def config_meter(self, range = 10):
+ if self.__port != 2:
+ range = int(range)
+
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:unit 0')
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:unit?')
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:range:auto 0') #Auto ranging turned off
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':pow:rang '+str(range)+'DBM')
+ self.gpib.write('trig'+str(int(self.__channel))+':inp:rearm on')
+
+ def prep_measure_on_trigger(self, samples = 64):
+ if self.__port != 2:
+ self.gpib.write('*CLS')
+ samples = int(samples)
+
+ #self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat stab,stop') #switch stab with logg depending
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat logg,stop') #switch stab with logg depending
+ self.gpib.write('trig'+str(int(self.__channel))+':chan'+str(int(self.__port))+':inp sme') #Set up trigger
+ print self.gpib.query('trig'+str(int(self.__channel))+':inp?')
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:par:logg '+str(samples)+',100us')
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:par:logg?')
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat logg,start')
+
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat?')
+ print self.gpib.query('syst:err?')
+
+
+ def get_result_from_log(self,samples=64):
+
+ if self.__port != 2:
+ print self.gpib.query('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:stat?')
+
+ self.gpib.write('sens'+str(int(self.__channel))+':chan'+str(int(self.__port))+':func:res?')
+ data = self.gpib.read_raw()
+ print self.gpib.query('syst:err?')
+
+
+ samples = int(samples)
+
+ #print data
+
+ NofDigits = int(data[1])
+
+ HexData = data[2+NofDigits:2+NofDigits+samples*4]
+
+ FloData = []
+
+ for x in range(0, samples*4-1,4):
+ dat = HexData[x:x+4]
+ val = struct.unpack('.
+'''
diff --git a/ProberControl/prober/instruments/PIXe_4140.py b/ProberControl/prober/instruments/PIXe_4140.py
new file mode 100644
index 0000000..645eafc
--- /dev/null
+++ b/ProberControl/prober/instruments/PIXe_4140.py
@@ -0,0 +1,181 @@
+""" Driver for NI PIXe-4322 6 channel SMU
+
+ Allows for user interfacing directly, as well as ProberControl API
+
+ see https://probercontrol.github.io/ProberControl/source/howto/addNewInstrument.html for
+ more info
+"""
+import sys
+import argparse
+
+import nidcpower
+
+class CustomFormatter(argparse.RawDescriptionHelpFormatter,
+ argparse.ArgumentDefaultsHelpFormatter):
+ pass
+
+def parse_args(args=sys.argv[1:]):
+ """Parse arguments."""
+ parser = argparse.ArgumentParser(
+ description=sys.modules[__name__].__doc__,
+ formatter_class=CustomFormatter)
+
+ g = parser.add_argument_group("driver settings")
+ g.add_argument("address", metavar="gpib_address",
+ type=str,
+ help="The address of the device to be controlled")
+ g.add_argument("channel", metavar="device_channel",
+ type=str,
+ help="The channel to be controlled for the device")
+ a = parser.add_argument_group("driver actions")
+ a.add_argument("function", metavar="function_name",
+ type=str,
+ help="The driver function to be run")
+ a.add_argument("--value", metavar="function value",
+ type=str,
+ help="The value to be set for the function")
+
+ return parser.parse_args(args)
+
+class PIXe_4140(object):
+ def __init__(self, rm, address='PXI1Slot2', channel='ao0', **kwargs):
+ self.address = address
+ self.channel = channel
+ self.last_set_voltage = 0
+ self.last_set_current = 0
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_enabled = False
+ session.initiate()
+
+ def setvoltage(self,value):
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_function = nidcpower.OutputFunction.DC_VOLTAGE
+ session.output_enabled = True
+ session.voltage_level_autorange = True
+ session.voltage_level = float(value)
+ session.initiate()
+
+ def setcurrent(self,value):
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_function = nidcpower.OutputFunction.DC_CURRENT
+ session.output_enabled = True
+ session.current_level_autorange = True
+ session.current_level = float(value)
+ session.initiate()
+
+ def set_voltage_get_voltage(self, value, query_range):
+ query_range = int(query_range)
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_function = nidcpower.OutputFunction.DC_VOLTAGE
+ session.output_enabled = True
+ session.voltage_level_autorange = True
+ session.measure_record_length = query_range
+ session.measure_record_length_is_finite = True
+ session.measure_when = nidcpower.MeasureWhen.AUTOMATICALLY_AFTER_SOURCE_COMPLETE
+ session.voltage_level = float(value)
+ samples = []
+ samples_acquired = 0
+ with session.initiate():
+ while samples_acquired < query_range:
+ measurements = session.fetch_multiple(count=session.fetch_backlog)
+ samples_acquired += len(measurements)
+ for i in range(len(measurements)):
+ samples.append(measurements[i].voltage)
+
+ return samples
+
+
+ def set_current_get_voltage(self, value, query_range):
+ query_range = int(query_range)
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_function = nidcpower.OutputFunction.DC_CURRENT
+ session.output_enabled = True
+ session.current_level_autorange = True
+ session.measure_record_length = query_range
+ session.measure_record_length_is_finite = True
+ session.measure_when = nidcpower.MeasureWhen.AUTOMATICALLY_AFTER_SOURCE_COMPLETE
+ session.current_level = float(value)
+ samples = []
+ samples_acquired = 0
+ with session.initiate():
+ while samples_acquired < query_range:
+ measurements = session.fetch_multiple(count=session.fetch_backlog)
+ samples_acquired += len(measurements)
+ for i in range(len(measurements)):
+ samples.append(measurements[i].voltage)
+
+ return samples
+
+ def set_voltage_get_current(self, value, query_range):
+ query_range = int(query_range)
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_function = nidcpower.OutputFunction.DC_VOLTAGE
+ session.output_enabled = True
+ session.voltage_level_autorange = True
+ session.measure_record_length = query_range
+ session.measure_record_length_is_finite = True
+ session.measure_when = nidcpower.MeasureWhen.AUTOMATICALLY_AFTER_SOURCE_COMPLETE
+ session.voltage_level = float(value)
+ samples = []
+ samples_acquired = 0
+ with session.initiate():
+ while samples_acquired < query_range:
+ measurements = session.fetch_multiple(count=session.fetch_backlog)
+ samples_acquired += len(measurements)
+ for i in range(len(measurements)):
+ samples.append(measurements[i].current)
+
+ return samples
+
+
+ def set_current_get_current(self, value, query_range):
+ query_range = int(query_range)
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_function = nidcpower.OutputFunction.DC_CURRENT
+ session.output_enabled = True
+ session.current_level_autorange = True
+ session.measure_record_length = query_range
+ session.measure_record_length_is_finite = True
+ session.measure_when = nidcpower.MeasureWhen.AUTOMATICALLY_AFTER_SOURCE_COMPLETE
+ session.current_level = float(value)
+ samples = []
+ samples_acquired = 0
+ with session.initiate():
+ while samples_acquired < query_range:
+ measurements = session.fetch_multiple(count=session.fetch_backlog)
+ samples_acquired += len(measurements)
+ for i in range(len(measurements)):
+ samples.append(measurements[i].current)
+
+ return samples
+
+ def retreive_voltage(self):
+ return self.voltage
+
+ def whoAmI(self):
+ return 'DCSource'
+
+ def source_off(self):
+ '''Release resources'''
+ with nidcpower.Session(resource_name=self.address, channels=self.channel) as session:
+ session.output_enabled = False
+ session.initiate()
+
+def main(options, stdout):
+ device = PIXe_4140(options.address,options.channel)
+ if hasattr(PIXe_4140, options.function):
+ if isempty(options.value):
+ value = getattr(device, options.function)
+ else:
+ value = getattr(device, options.function)(options.value)
+ print('Function: %s' % options.function)
+ else:
+ print("Function does not exist.")
+
+if __name__ == '__main__':
+ def _script_io():
+ from sys import argv, stdout
+ options = parse_args()
+ main(options, stdout)
+
+ _script_io()
diff --git a/ProberControl/prober/instruments/PIXe_4322.py b/ProberControl/prober/instruments/PIXe_4322.py
new file mode 100644
index 0000000..e0b2868
--- /dev/null
+++ b/ProberControl/prober/instruments/PIXe_4322.py
@@ -0,0 +1,78 @@
+""" Driver for NI PIXe_4322 8 channel Power Supply
+
+ Allows for user interfacing directly, as well as ProberControl API
+
+ see https://probercontrol.github.io/ProberControl/source/howto/addNewInstrument.html for
+ more info
+"""
+import sys
+import argparse
+
+import nidaqmx
+
+class CustomFormatter(argparse.RawDescriptionHelpFormatter,
+ argparse.ArgumentDefaultsHelpFormatter):
+ pass
+
+def parse_args(args=sys.argv[1:]):
+ """Parse arguments."""
+ parser = argparse.ArgumentParser(
+ description=sys.modules[__name__].__doc__,
+ formatter_class=CustomFormatter)
+
+ g = parser.add_argument_group("driver settings")
+ g.add_argument("address", metavar="gpib_address",
+ type=str,
+ help="The address of the device to be controlled")
+ g.add_argument("channel", metavar="device_channel",
+ type=str,
+ help="The channel to be controlled for the device")
+ a = parser.add_argument_group("driver actions")
+ a.add_argument("function", metavar="function_name",
+ type=str,
+ help="The driver function to be run")
+ a.add_argument("--value", metavar="function value",
+ type=str,
+ help="The value to be set for the function")
+
+ return parser.parse_args(args)
+
+class PIXe_4322(object):
+ def __init__(self, rm, address='PXI1Slot2', channel='ao0', **kwargs):
+ self.address = address
+ self.channel = channel
+ self.set_voltage(0)
+ self.voltage = 0
+ return
+
+ def set_voltage(self,value):
+ with nidaqmx.Task() as task:
+ print(self.address)
+ task.ao_channels.add_ao_voltage_chan(self.address + '/' + self.channel)
+ task.write(value)
+ task.stop()
+
+ def retreive_voltage(self):
+ return self.voltage
+
+ def whoAmI(self):
+ return 'PowerSupply'
+
+def main(options, stdout):
+ device = PIXe_4322(options.address,options.channel)
+ if hasattr(PIXe_4322, options.function):
+ if isempty(options.value):
+ value = getattr(device, options.function)
+ else:
+ value = getattr(device, options.function)(options.value)
+ print('Function: %s' % options.function)
+ else:
+ print("Function does not exist.")
+
+if __name__ == '__main__':
+ def _script_io():
+ from sys import argv, stdout
+ options = parse_args()
+ main(options, stdout)
+
+ _script_io()
diff --git a/ProberControl/prober/instruments/PSY_201.py b/ProberControl/prober/instruments/PSY_201.py
new file mode 100644
index 0000000..d008fac
--- /dev/null
+++ b/ProberControl/prober/instruments/PSY_201.py
@@ -0,0 +1,94 @@
+""" Driver for NI PIXe-4322 6 channel SMU
+
+ Allows for user interfacing directly, as well as ProberControl API
+
+ see https://probercontrol.github.io/ProberControl/source/howto/addNewInstrument.html for
+ more info
+"""
+import sys
+import visa
+import argparse
+
+import nidcpower
+
+class CustomFormatter(argparse.RawDescriptionHelpFormatter,
+ argparse.ArgumentDefaultsHelpFormatter):
+ pass
+
+def parse_args(args=sys.argv[1:]):
+ """Parse arguments."""
+ parser = argparse.ArgumentParser(
+ description=sys.modules[__name__].__doc__,
+ formatter_class=CustomFormatter)
+
+ g = parser.add_argument_group("driver settings")
+ g.add_argument("address", metavar="gpib_address",
+ type=str,
+ help="The address of the device to be controlled")
+ a = parser.add_argument_group("driver actions")
+ a.add_argument("function", metavar="function_name",
+ type=str,
+ help="The driver function to be run")
+ a.add_argument("--value", metavar="function value",
+ type=str,
+ help="The value to be set for the function")
+
+ return parser.parse_args(args)
+
+class PSY_201(object):
+ def __init__(self, res_manager, address='PXI1Slot2', **kwargs):
+ self.address = address
+ self.gpib = res_manager.open_resource(address)
+ self.gpib.clear()
+ self.gpib.write(':CONT:DIS')
+ self.track = False
+
+ def set_SOP(self,s1,s2,s3):
+ self.track = False
+ self.gpib.write(':CONT:SOP'+','.join([str(s1),str(s2),str(s3)]))
+
+ def set_SOP_type(self,type):
+ self.track = False
+ self.gpib.write(':CONT:TSC:TYPE'+str(int(type)))
+
+ def measure_polarization(self):
+ try:
+ return self.gpib.query(':MEAS:SOP?')
+ except:
+ return self.gpib.read()
+
+ def toggle_track_polarization(self):
+ if self.track:
+ self.gpib.write(':CONT:DIS')
+ else:
+ self.gpib.write(':CONT:ENAB')
+ self.track = not self.track
+
+ def measure_power(self):
+ try:
+ return self.gpib.query(':MEAS:POW?')
+ except:
+ return self.gpib.read()
+
+ def whoAmI(self):
+ return 'PolSynthesizer'
+
+def main(options, stdout):
+ #import visa
+ device = PIXe_1084(options.address,options.channel)
+ if hasattr(PIXe_1084, options.function):
+ if isempty(options.value):
+ value = getattr(device, options.function)
+ else:
+ value = getattr(device, options.function)(options.value)
+ print('Function: %s' % options.function)
+ else:
+ print("Function does not exist.")
+
+if __name__ == '__main__':
+ def _script_io():
+ from sys import argv, stdout
+ options = parse_args()
+ main(options, stdout)
+
+ _script_io()
diff --git a/ProberControl/prober/instruments/__init__.py b/ProberControl/prober/instruments/__init__.py
index e5e95b4..99fea03 100644
--- a/ProberControl/prober/instruments/__init__.py
+++ b/ProberControl/prober/instruments/__init__.py
@@ -36,7 +36,15 @@
'TL2500PowerDummy',
'TL2500MultiDummy',
'AgilentE3643A',
- 'TektronixCSA8000'
+ 'TektronixCSA8000',
+ 'PIXe_4140',
+ 'PIXe_4322',
+ 'PSY_201',
+ 'GenPhotPCD104',
+ 'Keysight8164B_PowerMeter',
+ 'Keysight8164B_Laser',
+ 'EXFOT100HP_Laser',
+ 'EXFOT100_Laser'
]
pipe_instrument_groups = {
diff --git a/ProberControl/prober/procedures/Measure.py b/ProberControl/prober/procedures/Measure.py
index 1c003aa..4f375f7 100644
--- a/ProberControl/prober/procedures/Measure.py
+++ b/ProberControl/prober/procedures/Measure.py
@@ -10,6 +10,20 @@
# Getting Global_MeasureHandler (singleton)instance; Do not change this!
gh = g()
+
+def testPM(maitre):
+
+ laser = gh.get_instrument('Laser')
+ print "laser "+str(laser)
+ #pm = gh.get_instrument_triggered_by(laser, 'PowerMeter')
+ pm = gh.get_instrument('PowerMeter')
+ print "PM "+str(pm)
+ gh.connect_instruments(laser, pm)
+ data = pm.get_power(float(1550))
+ print data
+
+
+
def test(maitre,data):
pl = NBPlot()
data = [data,data,data]
@@ -49,33 +63,35 @@ def get_o_spectrum_OSA(maitre,start, stop, step, result_path = 0):
return DataList
-def get_o_spectrum_PowerMeter(maitre,start, stop, step, channels, result_path = 0):
+def get_o_spectrum_triggered_PowerMeter(maitre,start, stop, step, channels = 1, result_path = 0):
start = float(start)
stop = float(stop)
step = float(step)
-
+
+ laser = gh.get_instrument('Laser')
+ laser.sweepWavelengthsContinuousTriggerOut(start, stop, step, speed = 5)
+
channels = int(channels)
- sweepWidth = stop-start
- sampleNumber = sweepWidth/(step) + 1
+ sampleNumber = laser.numberOfTriggers()
pms = []
for i in xrange(channels):
pm = gh.get_instrument('PowerMeter', additional=True)
- pm.config_meter(-30)
+ pm.config_meter(10)
pm.prep_measure_on_trigger(sampleNumber)
pms.append(pm)
+ laser.startSweep()
-
- t0 = time.time()
- osa = gh.get_instrument('OSA')
- OSAData = osa.get_o_spectrum(start, stop, step)
-
- time.sleep(3)
-
- AllDataList = [OSAData]
+ while laser.checkSweepStatus() == False:
+ pass
+
+ laser.reset()
+ #AllDataList = [OSAData]
+ AllDataList = []
+
for i in xrange(channels):
PowerList = pms[i].get_result_from_log(sampleNumber)
@@ -90,18 +106,20 @@ def get_o_spectrum_PowerMeter(maitre,start, stop, step, channels, result_path =
DataList.append([start+j*step, power])
#DataList.append([start+j*step, PowerList[j]])
pl = NBPlot()
- pl.plot(DataList,'Optical Spectrum for Channel ' + str(i),'Wavelength [nm]','Measured Power [dBm]')
+ pl.plot(DataList,'Optical Spectrum for Channel ' + str(i+1),'Wavelength [nm]','Measured Power [dBm]')
AllDataList.append(DataList)
#pl.plot(OSAData,'Optical Spectrum for OSA', 'Wavelength [nm]','Measured Power [dBm]')
-
+
+
+ pm.reset()
+
if result_path != 0:
- _write_data(OSAData,str(result_path)+'_OSA.txt')
- for i in range(len(AllDataList)):
- _write_data(AllDataList[i],str(result_path)+'_PM'+str(i)+'.txt')
-
+ #_write_data(OSAData,str(result_path)+'_OSA.txt')
+ for i in range(len(AllDataList)):
+ DataIO.writeData(result_path,AllDataList,'get_o_spectrum')
return AllDataList
@@ -110,24 +128,32 @@ def get_current(maitre):
data = dc.get_current()
return data
-def get_o_spectrum(maitre,start,stop,step,result_path=0):
+def get_o_spectrum_manual_PowerMeter(maitre,start,stop,step,result_path=0):
laser = gh.get_instrument('Laser')
- pm = gh.get_instrument_triggered_by(laser, 'PowerMeter')
+ print "laser "+str(laser)
+ #pm = gh.get_instrument_triggered_by(laser, 'PowerMeter')
+ pm = gh.get_instrument('PowerMeter')
+ print "PM "+str(pm)
+ gh.connect_instruments(laser, pm)
init_wavelength = float(laser.getwavelength())
- laser.sweepWavelengthsTriggerSetup(float(start),float(stop),float(step))
+ laser.sweepWavelengthsManual(float(start),float(stop),float(step))
DataList = []
+
+ print ("Sweeping"),
for x in np.arange(float(start),float(stop)+float(step),float(step)):
- laser.trigger()
- DataList.append([x,pm.get_o_power(x,True)])
+ print ("."),
+ laser.step()
+ DataList.append([x, pm.get_power(x)])
+ print ("Sweeping Complete")
laser.setwavelength(init_wavelength)
- pm.get_power(init_wavelength,channel)
+ pm.get_power(init_wavelength)
pl = NBPlot()
pl.plot(
diff --git a/ProberControl/prober/scripts/LPR_test.scr b/ProberControl/prober/scripts/LPR_test.scr
new file mode 100644
index 0000000..d993514
--- /dev/null
+++ b/ProberControl/prober/scripts/LPR_test.scr
@@ -0,0 +1,13 @@
+#Measurement Name
+Laser power reading
+#structure
+basic
+#procedure
+Measure
+#Function
+get_o_spectrum_triggered_PowerMeter
+#Arguments
+1550 1560 0.1 1 .\test_jd
+
+
+
diff --git a/ProberControl/results b/ProberControl/results
new file mode 100644
index 0000000..c6a7c0f
--- /dev/null
+++ b/ProberControl/results
@@ -0,0 +1,13 @@
+##get_o_spectrum_0:
+1550.0 5.12794365243
+1551.0 5.14616146384
+1552.0 5.15866391478
+1553.0 5.17285682962
+1554.0 5.18512742503
+1555.0 5.19459883212
+1556.0 5.20679939523
+1557.0 5.21124060407
+1558.0 5.23382057348
+1559.0 5.25570435147
+
+
diff --git a/ProberControl/results.csv b/ProberControl/results.csv
new file mode 100644
index 0000000..48d4fc7
--- /dev/null
+++ b/ProberControl/results.csv
@@ -0,0 +1,53 @@
+##get_o_spectrum_0:
+1550.0 5.12668137811
+1551.0 5.14497560509
+1552.0 5.15673051232
+1553.0 5.17130753887
+1554.0 5.18419551342
+1555.0 5.19333743572
+1556.0 5.2059694028
+1557.0 5.2106786189
+1558.0 5.23285904856
+1559.0 5.25470363441
+
+
+##get_o_spectrum_0:
+1550.0 6.0060122624
+1550.1 6.01696394509
+1550.2 6.02818939805
+1550.3 6.03239304939
+1550.4 6.04165566533
+1550.5 6.05048885929
+1550.6 6.05856844723
+1550.7 6.06732933053
+1550.8 6.07410390875
+1550.9 6.0781585997
+1551.0 6.08651559448
+1551.1 6.09205545795
+1551.2 6.0934771056
+1551.3 6.10417945774
+1551.4 6.11807945357
+1551.5 6.1325717397
+1553.0 -125.024355372
+1553.3 -232.29991543
+1553.5 -81.4968738708
+1553.8 45.776915136
+1554.1 -235.972561985
+1554.3 -282.673661258
+1555.0 -226.335678259
+1555.6 -201.096373707
+1555.8 -118.909057144
+1556.5 -344.588786861
+1556.7 -172.264793699
+1556.8 -55.6460362626
+1557.4 -283.31060688
+1557.6 -92.6967707225
+1557.7 -108.464662109
+1558.5 -243.062946221
+1558.8 -298.251076646
+1558.9 -147.93267167
+1559.5 -118.973441716
+1559.6 -239.630118139
+1559.8 -221.963300335
+
+
diff --git a/ProberControl/setup/requirements.txt b/ProberControl/setup/requirements.txt
index 0eed04b..7a1f8e6 100644
--- a/ProberControl/setup/requirements.txt
+++ b/ProberControl/setup/requirements.txt
@@ -61,4 +61,6 @@ widgetsnbextension==2.0.0
win-unicode-console==0.5
opencv-python==3.2.0.7
tqdm==4.11.2
-setuptools==18.5
\ No newline at end of file
+setuptools==18.5
+nidcpower==1.1.2
+nidaqmx==0.5.7
\ No newline at end of file