Commit 471562ec551e097a15fba641a50ead95743c9b39
0 parents
Exists in
master
first commit
Showing 1 changed file with 212 additions and 0 deletions Side-by-side Diff
AG53230A_freq_acq.py
| ... | ... | @@ -0,0 +1,212 @@ |
| 1 | +#!/usr/bin/env python | |
| 2 | +""" | |
| 3 | +Created on Mon Aug 19 15:52:23 2013 | |
| 4 | +53230a_freq_acq.py | |
| 5 | +This program is made to communicate with the counter | |
| 6 | +Agilent 53230A. | |
| 7 | +@author: Serge Grop | |
| 8 | +""" | |
| 9 | + | |
| 10 | +import sys | |
| 11 | +import argparse | |
| 12 | +import socket | |
| 13 | +import time | |
| 14 | +import os | |
| 15 | + | |
| 16 | +DEVICE_IP = '192.168.0.74' | |
| 17 | +DEVICE_PORT = 5025 # Agilent have standardized on using port 5025 for SCPI | |
| 18 | +#socket services. | |
| 19 | +GATE_TIME = 1 # Gate time for one measurement | |
| 20 | +OFILENAME = '' #File header | |
| 21 | +IN_COUP = 'AC' # Input coupling | |
| 22 | +IN_IMP = '50' # Input impedance | |
| 23 | +IN_CH = '1' # Input channel | |
| 24 | + | |
| 25 | +#============================================================================== | |
| 26 | +def parse(): | |
| 27 | + """ Specific parsing procedure for transfering data from 53230a | |
| 28 | + counter. | |
| 29 | + Return parsed arguments.""" | |
| 30 | + parser = argparse.ArgumentParser( \ | |
| 31 | + description='Acquire data from 53230a counter connected '\ | |
| 32 | + 'through Ethernet.', | |
| 33 | + epilog='Example: \'53230a_acq_freq -o toto -c DC -i 1M \' configure ' \ | |
| 34 | + '53230a_acq_freq with output file toto-"date".dat, input coupling DC '\ | |
| 35 | + 'and input impedance 1 MOhms.') | |
| 36 | + parser.add_argument('-o', action='store', dest='ofile', \ | |
| 37 | + default=OFILENAME,\ | |
| 38 | + help='Output data filename (default '+OFILENAME+')') | |
| 39 | + parser.add_argument('-c', action='store', dest='input_coupling', \ | |
| 40 | + default=IN_COUP,\ | |
| 41 | + help='Input coupling AC or DC (default '+IN_COUP+')') | |
| 42 | + parser.add_argument('-i', action='store', dest='input_impedance', \ | |
| 43 | + default=IN_IMP,\ | |
| 44 | + help='Input impedance 50 or 1M (default '+IN_IMP+')') | |
| 45 | + parser.add_argument('-t', action='store', dest='gatetime', \ | |
| 46 | + default=GATE_TIME,\ | |
| 47 | + help='Gate time for one measurement'\ | |
| 48 | + ' (default '+str(GATE_TIME)+' second)') | |
| 49 | + parser.add_argument('-ip', action='store', dest='ip', \ | |
| 50 | + default=DEVICE_IP, help='IP address of the counter'\ | |
| 51 | + ' (default '+str(DEVICE_IP)+')') | |
| 52 | + parser.add_argument('-p', action='store', dest='port', \ | |
| 53 | + default=DEVICE_PORT, help='Port of the counter'\ | |
| 54 | + ' (default '+str(DEVICE_PORT)+')') | |
| 55 | + parser.add_argument('-ch', action='store', dest='input_channel', \ | |
| 56 | + default=IN_CH,\ | |
| 57 | + help='Input channel (default '+IN_CH+')') | |
| 58 | + args = parser.parse_args() | |
| 59 | + return args | |
| 60 | + | |
| 61 | +#============================================================================== | |
| 62 | +def connect(ip,port): | |
| 63 | + """Creation of a socket to establish the communication | |
| 64 | + with 53230a counter""" | |
| 65 | + try: | |
| 66 | + print '53230a connection state at "%s" ?' % ip | |
| 67 | + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, \ | |
| 68 | + socket.IPPROTO_TCP) | |
| 69 | + sock.settimeout(5) # Don't hang around forever | |
| 70 | + sock.connect((ip, port)) # Start the connection | |
| 71 | + print ' --> Connected' | |
| 72 | + return sock | |
| 73 | + except socket.error as ex: # Debugging | |
| 74 | + if 'Connection refused' in ex: | |
| 75 | + print 'Wrong PORT (Default PORT : 5025)\n', ex | |
| 76 | + print '\n --> Not connected' | |
| 77 | + elif 'No route to host' in ex: | |
| 78 | + print 'Wrong address (Default address : 169.254.2.30)\n', ex | |
| 79 | + print '\n --> Not connected' | |
| 80 | + else: | |
| 81 | + print ex+'\n'+' --> Not connected' | |
| 82 | + sys.exit() | |
| 83 | + | |
| 84 | +#============================================================================== | |
| 85 | +def init_53230a(sock, coupling, impedance, gatetime, channel): | |
| 86 | + """Initialization of the counter""" | |
| 87 | + g_time = 'SENS:FREQ:GATE:TIME '+str(gatetime)+'\n' # Definition of | |
| 88 | + #the string to initialize the gate time | |
| 89 | + sock.send("*RST\n") #Main reset | |
| 90 | + sock.send("DISP:DIG:MASK:AUTO OFF\n") # Disable display autodigits | |
| 91 | + if impedance == '50': | |
| 92 | + sock.send("INP"+channel+":IMP 50\n") # Input 1 impedance : 50 Ohms | |
| 93 | + else: | |
| 94 | + sock.send("INP"+channel+":IMP 1.0E6\n") # Input 1 impedance : 1 MOhms | |
| 95 | + if coupling == 'AC': | |
| 96 | + sock.send("INP"+channel+":COUP AC\n") # Input 1 coupling mode AC | |
| 97 | + else: | |
| 98 | + sock.send("INP"+channel+":COUP DC\n") # Input 1 coupling mode DC | |
| 99 | + sock.send("SYST:TIM INF\n") # Timeout infiny to avoid problem if the gate | |
| 100 | + #is too long | |
| 101 | + sock.send("CONF:FREQ (@"+channel+")\n") # Signal on input 1 | |
| 102 | + sock.send("SAMP:COUN 1E6\n") # Number of samples : 1 million (max) | |
| 103 | + # the number of samples in continous mode is limited | |
| 104 | + # by the size of the memory | |
| 105 | + sock.send("SENS:FREQ:MODE CONT\n") # Continuous mode (gap free) enable | |
| 106 | + sock.send("SENS:FREQ:GATE:SOUR TIME\n") # The gate source is TIME | |
| 107 | + sock.send(g_time) # Gate time : 1 second | |
| 108 | + sock.send("TRIG:SOUR IMM\n") # Because of the continuous mode | |
| 109 | + | |
| 110 | +#============================================================================== | |
| 111 | +def check_error(sock): | |
| 112 | + """Used for debugging during the development of the program, | |
| 113 | + not used anymore""" | |
| 114 | + sock.send('SYST:ERR?\n') | |
| 115 | + error = None | |
| 116 | + try: | |
| 117 | + error = sock.recv(128) | |
| 118 | + except socket.timeout: | |
| 119 | + error = "" | |
| 120 | + print error | |
| 121 | + | |
| 122 | +#============================================================================== | |
| 123 | +def read_buffer(sock): | |
| 124 | + """Read the data returned by the counter 53230a until the '\n'""" | |
| 125 | + ans = '' | |
| 126 | + nb_data_list = [] | |
| 127 | + nb_data = '' | |
| 128 | + while ans != '\n': | |
| 129 | + ans = sock.recv(1) | |
| 130 | + nb_data_list.append(ans) # Return the number of data | |
| 131 | + list_size = len(nb_data_list) | |
| 132 | + for j in range (0, list_size): | |
| 133 | + nb_data = nb_data+nb_data_list[j] | |
| 134 | + return(nb_data) # Return the number of data in the memory | |
| 135 | + | |
| 136 | + | |
| 137 | +#============================================================================== | |
| 138 | +def acqu_53230a(i, sock, data_file, gatetime): | |
| 139 | + """Frequency acquisition and stockage in a file""" | |
| 140 | + sock.send("INIT:IMM\n") # Start the acquisition immediatly | |
| 141 | + print "Waiting for the first acquisition" | |
| 142 | + while True: | |
| 143 | + try: | |
| 144 | + sock.send("DATA:POIN?\n") # Ask the number of data in the memory | |
| 145 | + nb_data = read_buffer(sock) # Number of data available (string) | |
| 146 | + #nb_data_int = int(nb_data) # Convert in integer | |
| 147 | + #epoch time | |
| 148 | + epoch = time.time() | |
| 149 | + #MJD time | |
| 150 | + mjd = epoch / 86400.0 + 40587 | |
| 151 | + if nb_data != '+0\n': # There is a minimum of one data to read | |
| 152 | + try: | |
| 153 | + sock.send("DATA:REM? 1\n") # Put the data in the buffer and | |
| 154 | + # clear the memory | |
| 155 | + freq = sock.recv(24) # Read the buffer | |
| 156 | + freq = freq[:22] # Remove \n from the string | |
| 157 | + freq = freq.replace("+", "") | |
| 158 | + freq = freq.replace("E", "e") | |
| 159 | + freq = freq.replace("\t", "") | |
| 160 | + sample = "%f\t%f\t%s\n" % (epoch, mjd, freq) | |
| 161 | + data_file.write(sample) # Write in a file | |
| 162 | + print sample | |
| 163 | + except Exception as ex: | |
| 164 | + print "Exception during counter data reading: " + str(ex) | |
| 165 | + else: | |
| 166 | + #print "Waiting for the next acquisition" | |
| 167 | + #pass | |
| 168 | + time.sleep(int(gatetime)*0.1) # Wait the time of the gate time | |
| 169 | + #to avoid too much check of the memory | |
| 170 | + except KeyboardInterrupt: | |
| 171 | + break # To stop the loop in a clean way | |
| 172 | + | |
| 173 | +#============================================================================== | |
| 174 | +def main(): | |
| 175 | + """Main program""" | |
| 176 | + args = parse() # Parse command line | |
| 177 | + ofile = args.ofile # Data output file | |
| 178 | + ip = args.ip | |
| 179 | + coup = args.input_coupling | |
| 180 | + imp = args.input_impedance | |
| 181 | + gate_time = args.gatetime | |
| 182 | + port = args.port | |
| 183 | + ch = args.input_channel | |
| 184 | + i = 0 #Init the number of sample | |
| 185 | + sock = connect(ip, port) | |
| 186 | + filename = time.strftime("%Y%m%d-%H%M%S", \ | |
| 187 | + time.gmtime(time.time()))+'-AG53230A_cont.dat' # Define the name of the file : | |
| 188 | + # "experiment"+"date and hour".dat | |
| 189 | + data_file = open(filename, 'wr', 0) # Create the file in write and read | |
| 190 | + # mode, the file is updated at each sample | |
| 191 | + #data_file.write('#Number of the sample-frequency in Hz-'\ | |
| 192 | + #'date when the data is computed\n') | |
| 193 | + init_53230a(sock, coup, imp, gate_time, ch) | |
| 194 | + acqu_53230a(i, sock, data_file, gate_time) | |
| 195 | + sock.close() | |
| 196 | + print '\n --> Disconnected' | |
| 197 | + data_file.close() | |
| 198 | + try: | |
| 199 | + ans = raw_input('Would you like to keep this datafile'\ | |
| 200 | + '(y/n : default y)?\t') | |
| 201 | + if ans == 'n': | |
| 202 | + os.remove(filename) | |
| 203 | + print '\n', filename, 'removed\n' | |
| 204 | + else: | |
| 205 | + print '\n', filename, 'saved\n' | |
| 206 | + except Exception as ex: | |
| 207 | + print 'Oups '+str(ex) | |
| 208 | + print 'Program ending\n' | |
| 209 | + | |
| 210 | +#============================================================================== | |
| 211 | +if __name__ == "__main__": | |
| 212 | + main() |