X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=research%2FTCS%2Finterface.py;h=7553ab4dddc81319768f780a5031fb3491e05a12;hb=719c502e645607bc071ffbf41a455db899bef8a7;hp=b36a4e5edccacb6dc0744f8c2d4d0cae148cee65;hpb=56bf4ee27e40b03bdba614df60e71d40d2cac502;p=matches%2Fhonours.git diff --git a/research/TCS/interface.py b/research/TCS/interface.py index b36a4e5e..7553ab4d 100755 --- a/research/TCS/interface.py +++ b/research/TCS/interface.py @@ -12,7 +12,11 @@ import time import serial import datetime +import odict +import Gnuplot, Gnuplot.funcutils +import subprocess +gnuplot = Gnuplot.Gnuplot() # TODO: Insert variables for calibration purposes here. calibrate = { @@ -31,14 +35,15 @@ calibrate = { } # TODO: Adjust aqcuisition parameters here -aquire = { "DAC_Sweep" : "0.0 + 250.0*int(step/300)", # DAC Sweep value (t is in STEPS, not seconds!) - "ADC_Averages" : 200, - "ADC_Vi" : 5, # ADC channel to read back Vi (set by DAC) through - "ADC_Is" : 4, # ADC channel to read back Is through - "ADC_Ie" : 4, # ADC channel to read back Ie through +aquire = { "DAC_Sweep" : "0.0 + 1.0*int(step)", # DAC Sweep value (t is in STEPS, not seconds!) + "ADC_Averages" : 100, + #"ADC_Vi" : 5, # ADC channel to read back Vi (set by DAC) through + #"ADC_Is" : 4, # ADC channel to read back Is through + #"ADC_Ie" : 4, # ADC channel to read back Ie through "DAC_Settle" : 0.0, # Time in seconds to wait for DAC to stabilise #"response_wait" : 0.2, # Time to wait in seconds between sending data and reading back - "start_date" : None + "start_date" : None, + "open_files" : [] } #Setup the serial connection parameters @@ -54,22 +59,37 @@ ser = serial.Serial( xonxoff=0, rtscts=0 ) - -parameters = { - "Accelerating Voltage" : None, - "Focus Voltage" : None, - "Deflection Voltage" : None, - "Venault Voltage" : None, - "Initial Voltage" : None, - "Heating Current" : None, - "Heating Voltage" : None, - "Chamber Pressure" : None, - "602 0.1 Battery" : None, - "602 0.03 Battery" : None, - "602 0.01 Battery" : None, - "602 0.003 Battery" : None, - "602 0.001 Battery" : None -} +#Using an ordered dictionary, so results will be determined (or prompted for) in this order. +# Put things that are being changed a lot near the top of the list. +parameters = odict.odict([ + ("Chamber Pressure" , None), # Chamber pressure now automatically determined + ("Deflection Voltage" , None), + ("Title" , None), + ("Comment" , None), + ("602 Scale" , None), + ("Venault Voltage" , None), + ("Accelerating Voltage" , None), + ("Focus Voltage" , None), + + ("Initial Voltage" , None), + ("Heating Current" , None), + ("Heating Voltage (across filament)" , None), + ("Heating Voltage (across power supply)", None), + #("610B Zero" , None), + ("602 Zero" , None), + #("610B Scale" , None), + + ("602 0.1 Battery" , None), + ("602 0.03 Battery" , None), + ("602 0.01 Battery" , None), + ("602 0.003 Battery" , None), + ("602 0.001 Battery" , None), + ("Sample", None), + ("Sample Angle", None), + ("ADC Regulator" , None), + ("Data" , None), + ("Parameters last checked", None) +]) def getTime(): return str(datetime.datetime.now()).split(" ")[1].split(".")[0].replace(":","") @@ -77,9 +97,68 @@ def getTime(): def getDate(): return str(datetime.datetime.now()).split(" ")[0] -def init(): +def getPressure(): + + try: + p = subprocess.Popen("./pressure/get_pressure.sh", stdout=subprocess.PIPE) + #p = subprocess.Popen("./this_program_does_not_exist.sh", stdout=subprocess.PIPE) + #result = float("a") + result = float(p.stdout.readline().strip(" \r\n\t")) + except: + return 0.0 + return result + + +# Used for when I press Control-C to stop things +def set_exit_handler(func): + if os.name == "nt": + try: + import win32api + win32api.SetConsoleCtrlHandler(func, True) + except ImportError: + version = ".".join(map(str, sys.version_info[:2])) + raise Exception("pywin32 not installed for Python " + version) + else: + import signal + signal.signal(signal.SIGTERM, func) + signal.signal(signal.SIGINT, func) + +def killed_handler(signal, frame): + reason = "" + sys.stdout.write("\n# Reason for killing program? ") + reason = sys.stdin.readline().strip("\r\n ") + for out in aquire["open_files"]: + sys.stdout.write("# Closing file " + str(out) + "\n") + out.write("# Recieved KILL signal.\n# Reason: " + str(reason) + "\n") + log_close(out) + +def cleanup(): + for out in aquire["open_files"]: + out.write("# Program exits.\n") + log_close(out) + +def log_open(a, b): + result = open(a, b,0) + if (b == "w"): + result.write("# File opened at " + str(datetime.datetime.now()) + "\n") + aquire["open_files"].append(result) + return result + +def log_close(afile): + if (afile in aquire["open_files"]): + afile.write("# File closed at " + str(datetime.datetime.now()) + "\n") + aquire["open_files"].remove(afile) + + afile.close() + + +def init(): + #import atexit + #atexit.register(cleanup) + set_exit_handler(killed_handler) + aquire["start_date"] = getDate() @@ -92,90 +171,173 @@ def init(): # pass #while (ser.readline().strip("\r\n ") != "#"): # pass - time.sleep(1.0) + #time.sleep(1.0) ser.write("a "+str(aquire["ADC_Averages"]) + "\r\n") - print(ser.readline().strip("\r\n")) - print(ser.readline().strip("\r\n")) - print(ser.readline().strip("\r\n")) + ser.readline().strip("\r\n") + ser.readline().strip("\r\n") + ser.readline().strip("\r\n") + #print(ser.readline().strip("\r\n")) + #print(ser.readline().strip("\r\n")) + #print(ser.readline().strip("\r\n")) - print("Writing config information to config.dat...") - output = open("config.dat", "w", 1) + #print("Writing config information to config.dat...") + #output = log_open("config.dat", "w", 1) - output.write("# Initialise " + str(datetime.datetime.now()) + "\n") + #output.write("# Initialise " + str(datetime.datetime.now()) + "\n") - for field in calibrate: - output.write("# calibrate["+str(field)+"] = "+str(calibrate[field]) + "\n") - output.write("\n") - for field in aquire: - output.write("# aquire["+str(field)+"] = "+str(aquire[field]) + "\n") + #for field in calibrate: + # output.write("# calibrate["+str(field)+"] = "+str(calibrate[field]) + "\n") + #output.write("\n") + #for field in aquire: + # output.write("# aquire["+str(field)+"] = "+str(aquire[field]) + "\n") - output.write("# Ready " + str(datetime.datetime.now()) + "\n# EOF\n") - output.close() + #output.write("# Ready " + str(datetime.datetime.now()) + "\n# EOF\n") + #output.close() def main(): init() - if (loadCalibration_DAC() == False): - if (calibrateDAC() == False): - return -1 - if (loadCalibration_ADC(aquire["ADC_Is"]) == False): - if (calibrateADC_usingDAC(aquire["ADC_Is"], False) == False): - if (calibrateADC(aquire["ADC_Is"]) == False): - return -1 - - if (loadCalibration_ADC(aquire["ADC_Vi"]) == False): - if (calibrateADC_usingDAC(aquire["ADC_Vi"], True) == False): - if (calibrateADC(aquire["ADC_Vi"]) == False): - return -1 + # I haven't ever used calibrated results, and yet this code is still here, why??? + #if (loadCalibration_DAC() == False): + # if (calibrateDAC() == False): + # return -1 + #if (loadCalibration_ADC(aquire["ADC_Is"]) == False): + # if (calibrateADC_usingDAC(aquire["ADC_Is"], False) == False): + # if (calibrateADC(aquire["ADC_Is"]) == False): + # return -1 + + #if (loadCalibration_ADC(aquire["ADC_Vi"]) == False): + # if (calibrateADC_usingDAC(aquire["ADC_Vi"], True) == False): + # if (calibrateADC(aquire["ADC_Vi"]) == False): + # return -1 # Make directory for today, backup calibration files os.system("mkdir -p " + getDate()) - os.system("cp *.dat " + getDate() +"/") + #os.system("cp *.dat " + getDate() +"/") - #checkList() + checkList() + # Experiment # TODO: Modify data to record here sweep = 1 - #record_data([4, 5], getDate()+"/"+str(getTime())+".dat", None, None, "Measure emission&sample current varying with time, constant initial energy.") + #for i in range(0,1): while True: os.system("mkdir -p " + getDate()) - record_data([4, 5], getDate()+"/"+str(getTime())+".dat", None, 2250, "Test 610B as sample current ammeter .Sweep " + str(sweep) + " (started on " + aquire["start_date"]+")") + record_data([5], getDate()+"/"+str(getTime())+".dat", None, 4001) + + try: + pass + #os.system("echo \"Sweep number " + str(sweep) + " completed\" | festival --tts") + except: + pass sweep += 1 + #setDAC(500) + + try: + os.system("echo \"Experiment complete\" | festival --tts") + except: + pass def checkList(): + try: + input_file = log_open(getDate()+"/checklist", "r") + except: + input_file = None + + if (input_file != None): + for line in input_file: + k = line.split("=") + item = None + if (len(k) >= 2): + item = k[0].strip("# \r\n") + value = k[1].strip("# \r\n") + + if (item in parameters): + if item == "Chamber Pressure": + parameters[item] = getPressure() + else: + parameters[item] = value - output = open(getDate()+"/checklist", "w", 0) + #print("Checklist found. Overwrite? [Y/n]") + response = "" #sys.stdin.readline().strip(" \r\n") + if (response == "" or response == "y" or response == "Y"): + input_file = log_open(getDate()+"/checklist.old", "w") + for item in parameters: + input_file.write("# " + str(item) + " = " + str(parameters[item]) + "\n") + input_file.write("\n") + log_close(input_file) + input_file = None + + if (input_file == None): + for item in parameters: + if item == "Parameters last checked": + continue + if item == "Chamber Pressure": + #sys.stdout.write("\""+str(item)+"\" = " + str(parameters[item]) + " - get new pressure... ") + parameters[item] = getPressure() + #sys.stdout.write(str(parameters[item]) + "\n") + continue + + sys.stdout.write("\""+str(item)+"\" = " + str(parameters[item]) + " New value?: ") + response = sys.stdin.readline().strip("\r\n ") + if (response == "!"): + break + if (response != ""): + parameters[item] = response + sys.stdout.write("\n") + parameters["Parameters last checked"] = str(datetime.datetime.now()) + + + checklist = log_open(getDate()+"/checklist", "w") for item in parameters: - sys.stdout.write("Enter value for \""+str(item)+"\": ") - parameters[item] = sys.stdin.readline().strip("\r\n ") - sys.stdout.write("\n") - output.write(str(parameters[item]) + "\n") - + checklist.write("# "+str(item) + " = " + str(parameters[item]) + "\n") + #output_file.write("# "+str(item) + " = " + str(parameters[item]) + "\n") + log_close(checklist) + -def record_data(ADC_channels, output, pollTime = None, dac_max = None, comment = None): +def record_data(ADC_channels, output, pollTime = None, dac_max = None): + if (output != None): - output = [open(output, "w", 0), sys.stdout] - if (comment == None): - print("Enter a comment for the experiment.") - comment = sys.stdin.readline().strip("\r\n ") - output[0].write("# Comment: "+str(comment)+"\n") + gnuplot("set title \""+str(output)+"\"") + output = [log_open(output, "w"), sys.stdout] + else: + gnuplot("set title \"\"") output = [sys.stdout] + for field in aquire: + for out in output: + out.write("# aquire["+str(field)+"] = "+str(aquire[field]) + "\n") + + for out in output: + out.write("# Parameters:\n") + + parameters["Chamber Pressure"] = getPressure() # Update chamber pressure + + for field in parameters: + for out in output: + out.write("# "+str(field)+" = " + str(parameters[field]) + "\n") + + start_time = time.time() + gnuplot("set xlabel \"DAC (counts)\"") + gnuplot("set ylabel \"ADC (counts)\"") + + for out in output: + out.write("\n") out.write("# Experiment " + str(datetime.datetime.now()) + "\n") out.write("# Polling for " + str(pollTime) + "s.\n") - out.write("# DAC = " + str(aquire["DAC_Sweep"]) + "\n") + out.write("\n") out.write("# Data:\n") out.write("# time\tDAC") for channel in ADC_channels: @@ -183,16 +345,22 @@ def record_data(ADC_channels, output, pollTime = None, dac_max = None, comment = out.write("\n") step = 0 + data = [] # Keep track of data for dynamic plotting dacValue = int(eval(aquire["DAC_Sweep"])) if (setDAC(dacValue) == False): setDAC(dacValue) + time.sleep(2.0) while (pollTime == None or time.time() < start_time + pollTime): if (aquire["DAC_Sweep"] != None): nextDacValue = int(eval(aquire["DAC_Sweep"])) if (nextDacValue != dacValue): dacValue = nextDacValue + if (dacValue < 0): + break setDAC(dacValue) step += 1 + + if (dac_max != None and dacValue >= dac_max): break @@ -203,28 +371,40 @@ def record_data(ADC_channels, output, pollTime = None, dac_max = None, comment = for channel in ADC_channels: read = readADC(channel) if read == False: - print("Abort data collection") - return False + for out in output: + print("# Abort data collection due to failed ADC read") + if out != sys.stdout: + log_close(out) + return False raw_adc.append((channel, read[0], read[1])) end_time = time.time() for out in output: - out.write(str((measure_start + (end_time - measure_start)/2.0 - start_time))) + measure_time = measure_start + (end_time - measure_start)/2.0 - start_time + out.write(str(measure_time)) out.write("\t"+str(dacValue)) + data.append([measure_time, dacValue]) + for adc in raw_adc: out.write("\t" + str(adc[1]) + "\t" + str(adc[2])) + data[len(data)-1].append(adc[1]) + data[len(data)-1].append(adc[2]) out.write("\n") - + #gnuplot("set yrange [0:1023]") + #gnuplot("set xrange [0:4000]") + gnuplot("set xlabel \"DAC (counts)\"") + gnuplot("set ylabel \"Sample Current (ADC counts)\"") + gnuplot.plot(Gnuplot.Data(data, title="t = "+str(measure_time), with_="lp", using="2:3")) for out in output: if out != sys.stdout: - out.close() + log_close(out) return True def loadCalibration_ADC(channel): try: - input_file = open("calibrateADC"+str(channel)+".dat") + input_file = log_open("calibrateADC"+str(channel)+".dat") except: print("Couldn't find calibration file for ADC " + str(channel)) return False @@ -237,7 +417,7 @@ def loadCalibration_ADC(channel): else: split_line = l.split("\t") calibrate["ADC"][channel].append((float(split_line[0]), float(split_line[1]))) - input_file.close() + log_close(input_file) if (len(calibrate["ADC"][channel]) <= 0): print("Empty calibration file for ADC " + str(channel)) @@ -246,7 +426,7 @@ def loadCalibration_ADC(channel): def loadCalibration_DAC(): try: - input_file = open("calibrateDAC.dat") + input_file = log_open("calibrateDAC.dat") except: print("Couldn't find calibration file for DAC") return False @@ -265,7 +445,7 @@ def loadCalibration_DAC(): calibrate["DAC"].append((int(split_line[0]), float(split_line[1]))) - input_file.close() + log_close(input_file) if (len(calibrate["DAC"]) <= 0): print("Empty calibration file for DAC") @@ -374,7 +554,7 @@ def calibrateADC_usingDAC(channel, gain = True): return False calibrate["ADC"][channel] = [] - outfile = open("calibrateADC"+str(channel)+".dat", "w", 1) + outfile = log_open("calibrateADC"+str(channel)+".dat", "w") outfile.write("# Calibrate ADC " + str(channel) + "\n") outfile.write("# Start " + str(datetime.datetime.now()) + "\n") @@ -413,7 +593,7 @@ def calibrateADC_usingDAC(channel, gain = True): calibrate["ADC"][channel].append((value[0], input_value, value[1])) outfile.write("# Stop " + str(datetime.datetime.now()) + "\n# EOF\n") - outfile.close() + log_close(outfile) if (setDAC(0) == False): return False if (len(calibrate["ADC"][channel]) <= 0): @@ -423,7 +603,7 @@ def calibrateADC_usingDAC(channel, gain = True): def calibrateADC(channel): calibrate["ADC"][channel] = [] - outfile = open("calibrateADC"+str(channel)+".dat", "w", 1) + outfile = log_open("calibrateADC"+str(channel)+".dat", "w") outfile.write("# Calibrate ADC " + str(channel) + "\n") outfile.write("# Start " + str(datetime.datetime.now()) + "\n") @@ -448,7 +628,7 @@ def calibrateADC(channel): outfile.write("# Stop " + str(datetime.datetime.now()) + "\n# EOF\n") - outfile.close() + log_close(outfile) if (len(calibrate["ADC"][channel]) <= 0): print("Error: No calibration points taken for ADC " + str(channel)) return False @@ -458,7 +638,7 @@ def calibrateADC(channel): def calibrateDAC(): calibrate["DAC"] = [] - outfile = open("calibrateDAC.dat", "w", 1) + outfile = log_open("calibrateDAC.dat", "w") outfile.write("# Calibrate DAC\n") outfile.write("# Start " + str(datetime.datetime.now()) + "\n") @@ -500,7 +680,7 @@ def calibrateDAC(): level += stepSize outfile.write("# Stop " + str(datetime.datetime.now()) + "\n# EOF\n") - outfile.close() + log_close(outfile) if (len(calibrate["DAC"]) <= 0): print("Error: No calibration points taken for DAC") return False