Commit 471562ec551e097a15fba641a50ead95743c9b39
0 parents
Exists in
master
first commit
Showing 1 changed file with 212 additions and 0 deletions Inline Diff
AG53230A_freq_acq.py
| File was created | 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': |