def performOpen(self, options={}): VISA_Driver.performOpen(self, options) #Set the format for the output VISA_Driver.writeAndLog(self, 'FORM:ELEM VOLT,CURR,RES') #Put source modes to fixed (rather than sweep) VISA_Driver.writeAndLog(self, 'SOUR:CURR:MODE FIX; :SOUR:VOLT:MODE FIX')
def performSetValue(self, quant, value, sweepRate=0.0, options={}): """Perform the Set Value instrument operation. This function should return the actual value set by the instrument""" # check if set value and in sweep mode if quant.name in ('Voltage', 'Current'): # check limits (dStep, dMax) = self.getMaxValueAndSmallestStep() if abs(value) > dMax: # new value out of range, return error raise Exception( 'New value (%.6g) is out of range (max = %.6g)' % (value, dMax)) # calculate actual value based on smallest step size value = dStep * np.round(value / dStep) # check if sweep mode or output off, if not call generic driver if sweepRate == 0.0 or (not self.getValue('Output')): return VISA_Driver.performSetValue(self, quant, value, 0.0, options=options) # sweep mode, do it here # get old value to find sweep time and step size currValue = self.performGetValue(quant) if value == currValue: # already at the final value, return return value # if sweep range is less than two minimal steps, don't sweep if abs(value - currValue) < 2.5 * dStep: return VISA_Driver.performSetValue(self, quant, value, 0.0, options=options) dSweepTime = abs(value - currValue) / sweepRate # don't allow sweep times that are shorter than 0.1 s dSweepTime = max(dSweepTime, 0.1) sSweepTime = '%.1f' % dSweepTime sCmd = '*CLS;:PROG:REP 0;' + \ 'SLOP %s;' % sSweepTime + \ 'INT %s;' % sSweepTime + \ 'EDIT:STAR;' + \ ':SOUR:LEV %.6E;' % value + \ ':PROG:EDIT:END;' + \ ':PROG:RUN' self.is_sweeping = True VISA_Driver.writeAndLog(self, sCmd) # return target value return value else: # for all other quantities, call the generic VISA driver return VISA_Driver.performSetValue(self, quant, value, sweepRate, options=options)
def performStopSweep(self, quant, options={}): #This command is only necessary if in ramp mode if quant.name.startswith('Voltage'): mode = self.getValue('Voltage Mode') elif quant.name.startswith('Current'): mode = self.getValue('Voltage Mode') else: #if it is some other quant, call default function VISA_Driver.performStopSweep(self, quant, options) if mode == 'Ramp': VISA_Driver.writeAndLog(self, 'ABOR')
def performStopSweep(self, quant, options={}): # This command is only necessary if in ramp mode if quant.name.startswith("Voltage"): mode = self.getValue("Voltage Mode") elif quant.name.startswith("Current"): mode = self.getValue("Voltage Mode") else: # if it is some other quant, call default function VISA_Driver.performStopSweep(self, quant, options) if mode == "Ramp": VISA_Driver.writeAndLog(self, "ABOR")
def clearMessages(self): #Send version request so message buffer isn't empty VISA_Driver.writeAndLog(self, 'V') #Read message buffer in full, to clear any messages that were not previously cleared #(Uncleared messages seem to arise from fact that device seems to be comparatively slow to reply) reply = VISA_Driver.read(self, ignore_termination=True) self.log("Message buffer read on initialisation: " + reply) while not reply.startswith('IPS120'): #There was an error or incorrect value, try to clear message buffer again reply = VISA_Driver.read(self, ignore_termination=True) self.wait(delayTime) self.log("Message buffer read again: " + reply)
def clearMessages(self): #Send version request so message buffer isn't empty VISA_Driver.writeAndLog(self,'V') #Read message buffer in full, to clear any messages that were not previously cleared #(Uncleared messages seem to arise from fact that device seems to be comparatively slow to reply) reply = VISA_Driver.read(self,ignore_termination=True) self.log("Message buffer read on initialisation: "+reply) while not reply.startswith('IPS120'): #There was an error or incorrect value, try to clear message buffer again reply = VISA_Driver.read(self,ignore_termination=True) self.wait(delayTime) self.log("Message buffer read again: "+reply)
def performOpen(self,options={}): VISA_Driver.performOpen(self,options) self.wait(delayTime) """ #Switch to remote & unlocked mode #(command already in 'init:' field in INI file) VISA_Driver.writeAndLog('$C3') """ self.clearMessages() #Switch to extended resolution VISA_Driver.writeAndLog(self,'$Q4') #Clear clamped status, if applicable VISA_Driver.writeAndLog(self,'$A0') self.wait(delayTime)
def checkIfSweeping(self, quant, options={}): #Can't create quant instances from here, can only pass name of quant #Whereas system if type(quant) == str: name = quant else: name = quant.name if name == 'Source Voltage Level' or name == 'Source Current Level': #If sweeping, can't go into program edit mode #Can't see any other way of checking if program is running VISA_Driver.writeAndLog(self,'*CLS') #Clear any existing errors VISA_Driver.writeAndLog(self,'PROG:EDIT:STAR') #force an error if program running err = VISA_Driver.askAndLog(self,'SYST:ERR?') #Check if there's a 'program running' error #Separate error code and error message #error code = 0 -> no errors errCode = int(err.split(',')[0]) if errCode == -284: #There is a 'program running' error, so program must be sweeping return True elif errCode == 103: #There is a 'program being edited error' for some reason. Stop editing self.log("Program didn't stop properly") VISA_Driver.writeAndLog(self,'PROG:EDIT:END') return False else: VISA_Driver.writeAndLog(self,'PROG:EDIT:END') return False else: #Not checking one of the quants that can sweep return False
def performOpen(self, options={}): VISA_Driver.performOpen(self, options) self.wait(delayTime) """ #Switch to remote & unlocked mode #(command already in 'init:' field in INI file) VISA_Driver.writeAndLog('$C3') """ self.clearMessages() #Switch to extended resolution VISA_Driver.writeAndLog(self, '$Q4') #Clear clamped status, if applicable VISA_Driver.writeAndLog(self, '$A0') self.wait(delayTime)
def performSetValue(self, quant, value, sweepRate=0.001, options={}): if quant.name == 'Output': if value: VISA_Driver.writeAndLog(self,'OUTP:STAT ON') return True else: #Sweep source to zero before turning off, to avoid sudden jumps func = self.getValue('Function') if func == 'Voltage': self.sendValueToOther('Source Voltage Level',0) while self.checkIfSweeping('Source Voltage Level',options): self.wait(0.05) elif func == 'Current': self.sendValueToOther('Source Current Level',0) while self.checkIfSweeping('Source Current Level',options): self.wait(0.05) VISA_Driver.writeAndLog(self,'OUTP:STAT OFF') return False elif quant.name == 'Function': if value == 'Voltage': VISA_Driver.writeAndLog(self,'SOUR:FUNC VOLT') return 'Voltage' elif value == 'Current': VISA_Driver.writeAndLog(self,'SOUR:FUNC CURR') return 'Current' elif quant.name == 'Source Current Range' or quant.name == 'Source Voltage Range': VISA_Driver.writeAndLog(self,'SOUR:RANG '+str(value)) return value elif quant.name == 'Source Voltage Level' or quant.name == 'Source Current Level': self.log(quant.name+' value passed: '+str(value)) self.log('Sweep rate: '+str(sweepRate)) #Check current source level initValue = float(self.askAndLog('SOUR:LEV?')) if value == initValue: #if no change, do nothing return float(value) else: #It seems sometimes sweepRate is not passed to this function (e.g. when setting config) # Ensure that this never causes a jump in source levels if quant.name == 'Source Voltage Level': maxSweepRate = 0.03 #30mV/sec or 1.8V/min else: maxSweepRate = 0.03 #30mA/sec or 1.8A/min if sweepRate == 0 or sweepRate > maxSweepRate: sweepRate = maxSweepRate difference = abs(value - initValue) duration = difference/abs(sweepRate) #Note minimum duration is 0.1s duration = max(duration,0.1) cmd1 = 'PROG:REP 0; ' #Program doesn't repeat cmd2 = 'SLOP '+str(duration)+'; ' #Source takes this long to move between values cmd3 = 'INT '+str(duration)+'; ' #This much time between program steps cmd4 = 'EDIT:STAR; ' #Add points to program cmd5 = ':SOUR:LEV '+str(value)+'; ' #Add target point cmd6 = ':PROG:EDIT:END; ' #Stop adding points to program cmd7 = ':PROG:RUN' #Run program sCmd = cmd1+cmd2+cmd3+cmd4+cmd5+cmd6+cmd7 VISA_Driver.writeAndLog(self,sCmd) #Combine all the above into one string, then send it return float(value) else: self.log('No other quant names triggered: '+quant.name) return VISA_Driver.performSetValue(self,quant,value,options,sweepRate)
def performSetValue(self, quant, value, sweepRate=0.0, options={}): self.log('performSetValue called: ' + quant.name + ' value: ' + str(value)) if quant.name == 'Source on_off': if value == 'On': VISA_Driver.writeAndLog(self, 'OUTP:STAT 1') return 'On' else: #Sweep source to zero before turning off, to avoid sudden jumps func = self.getValue('Source function') if func == 'Voltage': self.sendValueToOther('Voltage Amplitude', 0) while self.sendValueToOther('Voltage Amplitude', 0) != 0: self.wait(0.1) elif func == 'Current': self.sendValueToOther('Current Amplitude', 0) while self.sendValueToOther('Voltage Amplitude', 0) != 0: self.wait(0.1) VISA_Driver.writeAndLog(self, 'OUTP:STAT 0') return 'Off' elif quant.name.endswith('Amplitude'): #Voltage Amplitude #Current Amplitude if quant.name.startswith('Voltage'): cmd = 'SOUR:VOLT' maxOutpDiff = 0.0005 #5mV/s #Program sets source every 0.1 seconds, so sweepRate = outpDiff/0.1 = 10*outpDiff #Note minimum output change is 5uV. else: cmd = 'SOUR:CURR' maxOutpDiff = 0.0001 initValue = float(VISA_Driver.askAndLog(self, cmd + '?')) outpDiff = value - initValue if outpDiff == 0: #Don't send if already at right value return value elif outpDiff > maxOutpDiff: #If program is trying to move to a value too far away instantly, # then override by changing value value = initValue + maxOutpDiff elif outpDiff < -maxOutpDiff: value = initValue - maxOutpDiff #Enter the (modified or unmodified) value VISA_Driver.writeAndLog(self, cmd + ' ' + str(value)) return value elif quant.name.startswith('Measure '): #Determine which variables are being measured quantDict = {'Measure Current':['CURR',False], \ 'Measure Voltage':['VOLT',False], \ 'Measure Resistance':['RES',False]} for key, list in quantDict.items(): list[1] = self.getValue(key) #If only one, turn off concurrency if sum(list[1] for list in quantDict.values()) == 1: VISA_Driver.writeAndLog(self, 'FUNC:CONC 0') else: VISA_Driver.writeAndLog(self, 'FUNC:CONC 1') #Enable appropriate functions for key, list in quantDict.items(): if list[1]: VISA_Driver.writeAndLog(self, 'FUNC:ON ' + '"' + list[0] + '"') else: VISA_Driver.writeAndLog(self, 'FUNC:OFF ' + '"' + list[0] + '"') return value elif quant.name.endswith('Range Mode'): #convert auto/manual to auto on, auto off comboDict = {'Manual': '0', 'Automatic': '1'} value = comboDict[value] #Check source mode func = self.getValue('Source function') if quant.name.startswith('Voltage'): if func == 'Voltage': #If quant matches source mode, set source range VISA_Driver.writeAndLog(self, 'SOUR:VOLT:RANG:AUTO ' + value) else: #Otherwise, set measurement range VISA_Driver.writeAndLog(self, 'SENS:VOLT:RANG:AUTO ' + value) elif quant.name.startswith('Current'): if func == 'Current': VISA_Driver.writeAndLog(self, 'SOUR:CURR:RANG:AUTO ' + value) else: VISA_Driver.writeAndLog(self, 'SENS:CURR:RANG:AUTO ' + value) elif quant.name.startswith('Resistance'): #If using manual resistance mode, do nothing if self.getValue('Resistance Measurement Mode') == 'Automatic': VISA_Driver.writeAndLog(self, 'SENS:RES:RANG:AUTO ' + value) return int(value) elif quant.name == 'Voltage Manual Range' or quant.name == 'Current Manual Range': #Check source mode func = self.getValue('Source function') if quant.name.startswith('Voltage'): if func == 'Voltage': #If quant matches source mode, set source range VISA_Driver.writeAndLog(self, 'SOUR:VOLT:RANG ' + str(value)) else: #Otherwise, set compliance rainge and measurement range VISA_Driver.writeAndLog( self, 'SENS:VOLT:PROT ' + str(value * 1.1)) VISA_Driver.writeAndLog(self, 'SENS:VOLT:RANG ' + str(value)) elif quant.name.startswith('Current'): if func == 'Current': VISA_Driver.writeAndLog(self, 'SOUR:CURR:RANG ' + str(value)) else: VISA_Driver.writeAndLog( self, 'SENS:CURR:PROT ' + str(value * 1.05)) VISA_Driver.writeAndLog(self, 'SENS:CURR:RANG ' + str(value)) return value elif quant.name == 'Averaging Time': self.log('Averaging called') NPLC = self.getValue('NPLC') self.log('NPLC: ' + str(NPLC)) repeat = self.getValue('Repeat Filter') self.log('repeat: ' + str(repeat)) medRank = self.getValue('Median Filter') self.log('medRank: ' + str(medRank)) avCount = self.getValue('Moving Filter') self.log('avCount: ' + str(avCount)) timeBase = 1.0 / 50.0 avTime = NPLC * timeBase * repeat * (2 * medRank + 1) * avCount self.setValue('Averaging Time', str(avTime)) return avTime else: return VISA_Driver.performSetValue(self, quant, value, options=options, sweepRate=sweepRate)
def performSetValue(self, quant, value, sweepRate=0.0, options={}): self.log("performSetValue called: " + quant.name + " value: " + str(value)) if quant.name == "Voltage Mode": if value == "Fixed": VISA_Driver.writeAndLog(self, "SOUR:VOLT:MODE FIX") elif value == "Ramp": # General settings for ramp function # Rtime, start:level, end:level are set when actually sweeping cmd = [] cmd.append("SOUR:VOLT:MODE ARB") cmd.append("SOUR:ARB:FUNC:SHAP RAMP") cmd.append("SOUR:ARB:COUN 1") cmd.append("SOUR:ARB:VOLT:RAMP:END:TIME 0") cmd.append("SOUR:ARB:VOLT:RAMP:STAR:TIME 0") sCmd = cmd.join("; :") VISA_Driver.writeAndLog(self, sCmd) elif quant.name.endswith("Amplitude"): # Voltage Amplitude # Current Amplitude if quant.name.startswith("Voltage"): cmd = "SOUR:VOLT" maxOutpDiff = 0.005 # Never change by more than 5mV else: cmd = "SOUR:CURR" maxOutpDiff = 0.001 # Never change by more than 1 mA initValue = VISA_Driver.askAndLog(self, cmd + "?") outpDiff = value - float(initValue) if outpDiff == 0: # Don't send if already at right value return value elif outpDiff > maxOutpDiff: # If program is trying to move to a value too far away instantly, # then override by changing value value = initValue + maxOutpDiff elif outpDiff < -maxOutpDiff: value = initValue - maxOutpDiff # Enter the (modified or unmodified) value VISA_Driver.writeAndLog(self, cmd + " " + str(value)) return value elif quant.name.endswith(" Ramp"): if quant.name.startswith("Voltage"): cmd = "SOUR:VOLT" cmd2 = "SOUR:ARB:VOLT:RAMP" maxSweepRate = 0.005 # Never sweep faster than 5mV/sec elif quant.name.startswith("Current"): cmd = "SOUR:CURR" cmd2 = "SOUR:ARB:CURR:RAMP" maxSweepRate = 0.001 # Never sweep faster than 1mA/sec self.log("getting init value for ramp") initValue = float(VISA_Driver.askAndLog(self, cmd + "?")) outpDiff = value - initValue if sweepRate == 0 or sweepRate > maxSweepRate: sweepRate = maxSweepRate rTime = abs(outpDiff) / sweepRate cmd = [] cmd.append(cmd2 + ":END:LEV " + str(value)) cmd.append(cmd2 + ":RTIM " + str(rTime)) cmd.append(cmd2 + ":STAR:LEV " + str(initValue)) cmd.append("TRIG") # Sends an immediate trigger for both source and measure actions sCmd = "; :".join(cmd) VISA_Driver.writeAndLog(self, sCmd) elif quant.name.startswith("Measure "): # Enable appropriate functions, if something has been updated if self.isConfigUpdated(): # Determine which variables are being measured quantDict = { "Measure Current": ["CURR", False], "Measure Voltage": ["VOLT", False], "Measure Resistance": ["RES", False], } for key, list in quantDict.items(): list[1] = self.getValue(key) if list[1]: VISA_Driver.writeAndLog(self, "FUNC:ON " + list[0]) else: VISA_Driver.writeAndLog(self, "FUNC:OFF " + list[0]) return value elif quant.name == "Measurement Speed Method": # No commands sent to device for this quantity return value else: return VISA_Driver.performSetValue(self, quant, value, options=options, sweepRate=sweepRate)
def performStopSweep(self,quant,options={}): VISA_Driver.writeAndLog(self,'SWEEP:HALT')
def performSetValue(self, quant, value, sweepRate=0.0, options={}): couplingModes = ['Coupling CFRQAB','Coupling CFRQAC','Coupling RFLVAB','Coupling RFLVAC'] self.log('Quant.name is: '+quant.name+' Set value') if quant.name[-1] == ')': #Add source selection string to beginning of every #source specific command (ensure setting affects right source) source = quant.name[-2] sourceCmd = 'SOURCE '+source+'; :' if quant.name == 'Combiner Mode': VISA_Driver.writeAndLog(self,'CMODE '+value) return value elif quant.name == couplingModes[0]: """ This function sets all coupling modes at once, so it should only be called once per set_config action. Note: COUPLING:MODE CFRQAB (for example) makes CFRQAB the only mode I.e. modes can't be added one by one """ modeCmds = [] for cMode in couplingModes: if self.getValue(cMode) == True: self.log('Adding: '+cMode) modeCmds.append(cMode.split(' ')[1]) if len(modeCmds) == 0: cmdStr = 'COUPLING:MODE DISABLED' else: cmdStr = 'COUPLING:MODE '+','.join(modeCmds) VISA_Driver.writeAndLog(self,cmdStr) elif quant.name in couplingModes: pass elif quant.name.startswith('Coupling'): cmd = quant.name.split(' ') """ cmd[0] = 'Coupling' cmd[1] = one of the coupling modes cmd[2] = MODE, HARM, SUBHARM, OFFSET """ if cmd[2] == 'MODE': comboDict = {'Harmonic':'HARM','Sub-harmonic':'SUBHARM'} VISA_Driver.writeAndLog(self,'COUPLING:'+cmd[1]+':'+cmd[2]+' '+comboDict[value]) else: VISA_Driver.writeAndLog(self,'COUPLING:'+cmd[1]+':'+cmd[2]+' '+str(value)) elif quant.name.startswith('Carrier Frequency'): initValue = self.readValueFromOther(quant.name,options) initValue = float(initValue) if value == initValue: return initValue elif sweepRate != 0: """ Sweeping is done by continuously setting frequency Minimum time between steps is 50msec """ valueDiff = value - initValue time = abs(valueDiff)/sweepRate increment = 0.05*sweepRate #Sweep to point cmd = 'SWEEP:'+sourceCmd cmd += 'SWEEP:TRIG STARTSTOP; ' cmd += 'SWEEP:CFRQ:START '+str(initValue)+'; ' cmd +='STOP '+str(value)+'; ' cmd += 'TIME 0.05S; ' cmd += 'INC '+str(increment)+'; ' cmd += ':SWEEP:GO' VISA_Driver.writeAndLog(self,cmd) else: VISA_Driver.writeAndLog(self,sourceCmd+'CFRQ:VALUE '+str(value)+'HZ') elif quant.name.startswith('Carrier Phase offset'): VISA_Driver.writeAndLog(self,sourceCmd+'CFRQ:PHASE '+str(value)+'DEG') elif quant.name.startswith('RF Output On'): if value: VISA_Driver.writeAndLog(self,sourceCmd+'RFLV:ON') else: VISA_Driver.writeAndLog(self,sourceCmd+'RFLV:OFF') elif quant.name.startswith('RF Level'): VISA_Driver.writeAndLog(self,sourceCmd+'RFLV:VALUE '+str(value)+'DBM') elif quant.name.startswith('RF Type'): VISA_Driver.writeAndLog(self,sourceCmd+'RFLV:TYPE '+str(value)) elif quant.name.startswith('Modulation Control'): if value: VISA_Driver.writeAndLog(self,sourceCmd+'MOD:ON') else: VISA_Driver.writeAndLog(self,sourceCmd+'MOD:OFF') elif quant.name.startswith('Modulation mode'): modeList = [] pulse = self.getValue('Pulse Modulation ('+source+')') if 'AM' in value: modeList.append('AM') if 'FM' in value: modeList.append('FM') if 'PM' in value: modeList.append('PM') if 'FSK2L' in value: modeList.append('FSK2L') if 'FSK4L' in value: modeList.append('FSK4L') if pulse: modeList.append('PULSE') VISA_Driver.writeAndLog(self,'MODE '+','.join(modeList)) elif quant.name.startswith('Frequency Modulation Type'): if value: VISA_Driver.writeAndLog(self,sourceCmd+'FM:OFF; :FM1:ON; :FM2:ON') else: VISA_Driver.writeAndLog(self,sourceCmd+'FM:ON; :FM1:OFF; :FM2:OFF') elif quant.name.startswith('Phase Modulation Type'): if value: VISA_Driver.writeAndLog(self,sourceCmd+'PM:OFF; :PM1:ON; :PM2:ON') else: VISA_Driver.writeAndLog(self,sourceCmd+'PM:ON; :PM1:OFF; :PM2:OFF') elif quant.name.startswith('Pulse Modulation'): if value: VISA_Driver.writeAndLog(self,'PULSE:ON') else: VISA_Driver.writeAndLog(self,'PULSE:OFF') elif quant.name[:2] in ['FM','PM','AM']: cmd = quant.name.split(' ') """ cmd[0] = FM1, FM2, PM1, PM2, AM1, or AM2 cmd[1] = Deviation, Source, Modulation, Waveform, Phase, (Depth for AM), Status """ if cmd[1] == 'Status': if value: VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':ON') else: VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':OFF') elif cmd[1] == 'Deviation': VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':DEVN '+str(value)) elif cmd[1] == 'Source': comboDict = {'Internal':'INT','External AC':'EXTAC','External ALC':'EXTALC','External DC':'EXTDC'} VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':'+comboDict[value]) elif cmd[1] == 'Modulation': VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':MODF:VALUE '+str(value)+'HZ') elif cmd[1] == 'Waveform': VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':MODF:'+str(value)) elif cmd[1] == 'Phase': VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':MODF:PHASE '+str(value)+'DEG') elif cmd[1] == 'Depth': VISA_Driver.writeAndLog(self,sourceCmd+cmd[0]+':DEPTH '+str(value)+'PCT') else: self.log('Unknown command received: '+cmd[1]) elif quant.name.startswith('DC FM'): VISA_Driver.writeAndLog(self,sourceCmd+'DCFMNL') elif quant.name.endswith('Connected'): return value else: self.log('No quant name triggered') return VISA_Driver.performSetValue(self,quant,value,options,sweepRate) return value
def performStopSweep(self,quant,options={}): VISA_Driver.writeAndLog(self,'PROG:PAUS')
def performOpen(self, options={}): VISA_Driver.performOpen(self, options=options) # Set the format for the output VISA_Driver.writeAndLog(self, "FORM:ELEM:SENS VOLT,CURR,RES") # Put source modes to fixed (rather than sweep) VISA_Driver.writeAndLog(self, "SOUR:CURR:MODE FIX; :SOUR:VOLT:MODE FIX")
def performSetValue(self, quant, value, sweepRate=0.0, options={}): couplingModes = [ 'Coupling CFRQAB', 'Coupling CFRQAC', 'Coupling RFLVAB', 'Coupling RFLVAC' ] self.log('Quant.name is: ' + quant.name + ' Set value') if quant.name[-1] == ')': #Add source selection string to beginning of every #source specific command (ensure setting affects right source) source = quant.name[-2] sourceCmd = 'SOURCE ' + source + '; :' if quant.name == 'Combiner Mode': VISA_Driver.writeAndLog(self, 'CMODE ' + value) return value elif quant.name == couplingModes[0]: """ This function sets all coupling modes at once, so it should only be called once per set_config action. Note: COUPLING:MODE CFRQAB (for example) makes CFRQAB the only mode I.e. modes can't be added one by one """ modeCmds = [] for cMode in couplingModes: if self.getValue(cMode) == True: self.log('Adding: ' + cMode) modeCmds.append(cMode.split(' ')[1]) if len(modeCmds) == 0: cmdStr = 'COUPLING:MODE DISABLED' else: cmdStr = 'COUPLING:MODE ' + ','.join(modeCmds) VISA_Driver.writeAndLog(self, cmdStr) elif quant.name in couplingModes: pass elif quant.name.startswith('Coupling'): cmd = quant.name.split(' ') """ cmd[0] = 'Coupling' cmd[1] = one of the coupling modes cmd[2] = MODE, HARM, SUBHARM, OFFSET """ if cmd[2] == 'MODE': comboDict = {'Harmonic': 'HARM', 'Sub-harmonic': 'SUBHARM'} VISA_Driver.writeAndLog( self, 'COUPLING:' + cmd[1] + ':' + cmd[2] + ' ' + comboDict[value]) else: VISA_Driver.writeAndLog( self, 'COUPLING:' + cmd[1] + ':' + cmd[2] + ' ' + str(value)) elif quant.name.startswith('Carrier Frequency'): initValue = self.readValueFromOther(quant.name, options) initValue = float(initValue) if value == initValue: return initValue elif sweepRate != 0: """ Sweeping is done by continuously setting frequency Minimum time between steps is 50msec """ valueDiff = value - initValue time = abs(valueDiff) / sweepRate increment = 0.05 * sweepRate #Sweep to point cmd = 'SWEEP:' + sourceCmd cmd += 'SWEEP:TRIG STARTSTOP; ' cmd += 'SWEEP:CFRQ:START ' + str(initValue) + '; ' cmd += 'STOP ' + str(value) + '; ' cmd += 'TIME 0.05S; ' cmd += 'INC ' + str(increment) + '; ' cmd += ':SWEEP:GO' VISA_Driver.writeAndLog(self, cmd) else: VISA_Driver.writeAndLog( self, sourceCmd + 'CFRQ:VALUE ' + str(value) + 'HZ') elif quant.name.startswith('Carrier Phase offset'): VISA_Driver.writeAndLog( self, sourceCmd + 'CFRQ:PHASE ' + str(value) + 'DEG') elif quant.name.startswith('RF Output On'): if value: VISA_Driver.writeAndLog(self, sourceCmd + 'RFLV:ON') else: VISA_Driver.writeAndLog(self, sourceCmd + 'RFLV:OFF') elif quant.name.startswith('RF Level'): VISA_Driver.writeAndLog( self, sourceCmd + 'RFLV:VALUE ' + str(value) + 'DBM') elif quant.name.startswith('RF Type'): VISA_Driver.writeAndLog(self, sourceCmd + 'RFLV:TYPE ' + str(value)) elif quant.name.startswith('Modulation Control'): if value: VISA_Driver.writeAndLog(self, sourceCmd + 'MOD:ON') else: VISA_Driver.writeAndLog(self, sourceCmd + 'MOD:OFF') elif quant.name.startswith('Modulation mode'): modeList = [] pulse = self.getValue('Pulse Modulation (' + source + ')') if 'AM' in value: modeList.append('AM') if 'FM' in value: modeList.append('FM') if 'PM' in value: modeList.append('PM') if 'FSK2L' in value: modeList.append('FSK2L') if 'FSK4L' in value: modeList.append('FSK4L') if pulse: modeList.append('PULSE') VISA_Driver.writeAndLog(self, 'MODE ' + ','.join(modeList)) elif quant.name.startswith('Frequency Modulation Type'): if value: VISA_Driver.writeAndLog(self, sourceCmd + 'FM:OFF; :FM1:ON; :FM2:ON') else: VISA_Driver.writeAndLog( self, sourceCmd + 'FM:ON; :FM1:OFF; :FM2:OFF') elif quant.name.startswith('Phase Modulation Type'): if value: VISA_Driver.writeAndLog(self, sourceCmd + 'PM:OFF; :PM1:ON; :PM2:ON') else: VISA_Driver.writeAndLog( self, sourceCmd + 'PM:ON; :PM1:OFF; :PM2:OFF') elif quant.name.startswith('Pulse Modulation'): if value: VISA_Driver.writeAndLog(self, 'PULSE:ON') else: VISA_Driver.writeAndLog(self, 'PULSE:OFF') elif quant.name[:2] in ['FM', 'PM', 'AM']: cmd = quant.name.split(' ') """ cmd[0] = FM1, FM2, PM1, PM2, AM1, or AM2 cmd[1] = Deviation, Source, Modulation, Waveform, Phase, (Depth for AM), Status """ if cmd[1] == 'Status': if value: VISA_Driver.writeAndLog(self, sourceCmd + cmd[0] + ':ON') else: VISA_Driver.writeAndLog(self, sourceCmd + cmd[0] + ':OFF') elif cmd[1] == 'Deviation': VISA_Driver.writeAndLog( self, sourceCmd + cmd[0] + ':DEVN ' + str(value)) elif cmd[1] == 'Source': comboDict = { 'Internal': 'INT', 'External AC': 'EXTAC', 'External ALC': 'EXTALC', 'External DC': 'EXTDC' } VISA_Driver.writeAndLog( self, sourceCmd + cmd[0] + ':' + comboDict[value]) elif cmd[1] == 'Modulation': VISA_Driver.writeAndLog( self, sourceCmd + cmd[0] + ':MODF:VALUE ' + str(value) + 'HZ') elif cmd[1] == 'Waveform': VISA_Driver.writeAndLog( self, sourceCmd + cmd[0] + ':MODF:' + str(value)) elif cmd[1] == 'Phase': VISA_Driver.writeAndLog( self, sourceCmd + cmd[0] + ':MODF:PHASE ' + str(value) + 'DEG') elif cmd[1] == 'Depth': VISA_Driver.writeAndLog( self, sourceCmd + cmd[0] + ':DEPTH ' + str(value) + 'PCT') else: self.log('Unknown command received: ' + cmd[1]) elif quant.name.startswith('DC FM'): VISA_Driver.writeAndLog(self, sourceCmd + 'DCFMNL') elif quant.name.endswith('Connected'): return value else: self.log('No quant name triggered') return VISA_Driver.performSetValue(self, quant, value, options, sweepRate) return value
def performSetValue(self, quant, value, sweepRate=0.0, options={}): self.log('performSetValue called: ' + quant.name + ' value: ' + str(value)) if quant.name == 'Voltage Mode': if value == 'Fixed': VISA_Driver.writeAndLog(self, 'SOUR:VOLT:MODE FIX') elif value == 'Ramp': #General settings for ramp function #Rtime, start:level, end:level are set when actually sweeping cmd = [] cmd.append('SOUR:VOLT:MODE ARB') cmd.append('SOUR:ARB:FUNC:SHAP RAMP') cmd.append('SOUR:ARB:COUN 1') cmd.append('SOUR:ARB:VOLT:RAMP:END:TIME 0') cmd.append('SOUR:ARB:VOLT:RAMP:STAR:TIME 0') sCmd = cmd.join('; :') VISA_Driver.writeAndLog(self, sCmd) elif quant.name.endswith('Amplitude'): #Voltage Amplitude #Current Amplitude if quant.name.startswith('Voltage'): cmd = 'SOUR:VOLT' maxOutpDiff = 0.005 #Never change by more than 5mV else: cmd = 'SOUR:CURR' maxOutpDiff = 0.001 #Never change by more than 1 mA initValue = VISA_Driver.askAndLog(self, cmd + '?') outpDiff = value - float(initValue) if outpDiff == 0: #Don't send if already at right value return value elif outpDiff > maxOutpDiff: #If program is trying to move to a value too far away instantly, # then override by changing value value = initValue + maxOutpDiff elif outpDiff < -maxOutpDiff: value = initValue - maxOutpDiff #Enter the (modified or unmodified) value VISA_Driver.writeAndLog(self, cmd + ' ' + str(value)) return value elif quant.name.endswith(' Ramp'): if quant.name.startswith('Voltage'): cmd = 'SOUR:VOLT' cmd2 = 'SOUR:ARB:VOLT:RAMP' maxSweepRate = 0.005 #Never sweep faster than 5mV/sec elif quant.name.startswith('Current'): cmd = 'SOUR:CURR' cmd2 = 'SOUR:ARB:CURR:RAMP' maxSweepRate = 0.001 #Never sweep faster than 1mA/sec self.log("getting init value for ramp") initValue = float(VISA_Driver.askAndLog(self, cmd + '?')) outpDiff = value - initValue if sweepRate == 0 or sweepRate > maxSweepRate: sweepRate = maxSweepRate rTime = abs(outpDiff) / sweepRate cmd = [] cmd.append(cmd2 + ':END:LEV ' + str(value)) cmd.append(cmd2 + ':RTIM ' + str(rTime)) cmd.append(cmd2 + ':STAR:LEV ' + str(initValue)) cmd.append( 'TRIG' ) #Sends an immediate trigger for both source and measure actions sCmd = '; :'.join(cmd) VISA_Driver.writeAndLog(self, sCmd) elif quant.name.startswith('Measure '): #Enable appropriate functions, if something has been updated if self.isConfigUpdated(): #Determine which variables are being measured quantDict = {'Measure Current':['CURR',False], \ 'Measure Voltage':['VOLT',False], \ 'Measure Resistance':['RES',False]} for key, list in quantDict.items(): list[1] = self.getValue(key) if list[1]: VISA_Driver.writeAndLog(self, 'FUNC:ON ' + list[0]) else: VISA_Driver.writeAndLog(self, 'FUNC:OFF ' + list[0]) return value elif quant.name == "Measurement Speed Method": #No commands sent to device for this quantity return value else: return VISA_Driver.performSetValue(self, quant, value, options=options, sweepRate=sweepRate)
def performStopSweep(self, quant, options={}): VISA_Driver.writeAndLog(self, 'SWEEP:HALT')
def performSetValue(self, quant, value, sweepRate=0.0, options={}): self.log('performSetValue called: '+quant.name+' value: '+str(value)) if quant.name == 'Source on_off': if value == 'On': VISA_Driver.writeAndLog(self,'OUTP:STAT 1') return 'On' else: #Sweep source to zero before turning off, to avoid sudden jumps func = self.getValue('Source function') if func == 'Voltage': self.sendValueToOther('Voltage Amplitude',0) while self.sendValueToOther('Voltage Amplitude',0) != 0: self.wait(0.1) elif func == 'Current': self.sendValueToOther('Current Amplitude',0) while self.sendValueToOther('Voltage Amplitude',0) != 0: self.wait(0.1) VISA_Driver.writeAndLog(self,'OUTP:STAT 0') return 'Off' elif quant.name.endswith('Amplitude'): #Voltage Amplitude #Current Amplitude if quant.name.startswith('Voltage'): cmd = 'SOUR:VOLT' maxOutpDiff = 0.0005 #5mV/s #Program sets source every 0.1 seconds, so sweepRate = outpDiff/0.1 = 10*outpDiff #Note minimum output change is 5uV. else: cmd = 'SOUR:CURR' maxOutpDiff = 0.0001 initValue = float(VISA_Driver.askAndLog(self,cmd+'?')) outpDiff = value-initValue if outpDiff == 0: #Don't send if already at right value return value elif outpDiff > maxOutpDiff: #If program is trying to move to a value too far away instantly, # then override by changing value value = initValue+maxOutpDiff elif outpDiff < -maxOutpDiff: value = initValue-maxOutpDiff #Enter the (modified or unmodified) value VISA_Driver.writeAndLog(self,cmd+' '+str(value)) return value elif quant.name.startswith('Measure '): #Determine which variables are being measured quantDict = {'Measure Current':['CURR',False], \ 'Measure Voltage':['VOLT',False], \ 'Measure Resistance':['RES',False]} for key,list in quantDict.items(): list[1] = self.getValue(key) #If only one, turn off concurrency if sum(list[1] for list in quantDict.values()) == 1: VISA_Driver.writeAndLog(self,'FUNC:CONC 0') else: VISA_Driver.writeAndLog(self,'FUNC:CONC 1') #Enable appropriate functions for key,list in quantDict.items(): if list[1]: VISA_Driver.writeAndLog(self,'FUNC:ON '+'"'+list[0]+'"') else: VISA_Driver.writeAndLog(self,'FUNC:OFF '+'"'+list[0]+'"') return value elif quant.name.endswith('Range Mode'): #convert auto/manual to auto on, auto off comboDict = {'Manual':'0','Automatic':'1'} value = comboDict[value] #Check source mode func = self.getValue('Source function') if quant.name.startswith('Voltage'): if func == 'Voltage': #If quant matches source mode, set source range VISA_Driver.writeAndLog(self,'SOUR:VOLT:RANG:AUTO '+value) else: #Otherwise, set measurement range VISA_Driver.writeAndLog(self,'SENS:VOLT:RANG:AUTO '+value) elif quant.name.startswith('Current'): if func == 'Current': VISA_Driver.writeAndLog(self,'SOUR:CURR:RANG:AUTO '+value) else: VISA_Driver.writeAndLog(self,'SENS:CURR:RANG:AUTO '+value) elif quant.name.startswith('Resistance'): #If using manual resistance mode, do nothing if self.getValue('Resistance Measurement Mode') == 'Automatic': VISA_Driver.writeAndLog(self,'SENS:RES:RANG:AUTO '+value) return int(value) elif quant.name == 'Voltage Manual Range' or quant.name == 'Current Manual Range' : #Check source mode func = self.getValue('Source function') if quant.name.startswith('Voltage'): if func == 'Voltage': #If quant matches source mode, set source range VISA_Driver.writeAndLog(self,'SOUR:VOLT:RANG '+str(value)) else: #Otherwise, set compliance rainge and measurement range VISA_Driver.writeAndLog(self,'SENS:VOLT:PROT '+str(value*1.1)) VISA_Driver.writeAndLog(self,'SENS:VOLT:RANG '+str(value)) elif quant.name.startswith('Current'): if func == 'Current': VISA_Driver.writeAndLog(self,'SOUR:CURR:RANG '+str(value)) else: VISA_Driver.writeAndLog(self,'SENS:CURR:PROT '+str(value*1.05)) VISA_Driver.writeAndLog(self,'SENS:CURR:RANG '+str(value)) return value elif quant.name == 'Averaging Time': self.log('Averaging called') NPLC = self.getValue('NPLC') self.log('NPLC: '+str(NPLC)) repeat = self.getValue('Repeat Filter') self.log('repeat: '+str(repeat)) medRank = self.getValue('Median Filter') self.log('medRank: '+str(medRank)) avCount = self.getValue('Moving Filter') self.log('avCount: '+str(avCount)) timeBase = 1.0/50.0 avTime = NPLC*timeBase*repeat*(2*medRank+1)*avCount self.setValue('Averaging Time',str(avTime)) return avTime else: return VISA_Driver.performSetValue(self,quant,value,options=options,sweepRate=sweepRate)