esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE% par263cyc1.mac $Revision: 1.2 $
#%NAME%
#   Princeton Applied Research Potentiostat/Galvanostat model 263A and
#   model VersaStatII 2532
#%DESCRIPTION%
# macro written by Frederik Golks (ID32) (18/02/2009) %BR%
# based on macro by Manuel Perez %BR%
# what it should do: %BR%
#	1.) take CVs with n cycles %BR%
#	2.) print the CV during the measurement to the screen %BR%
#	3.) safe the CV(s) afterwards to file %BR%
#	4.) keep final potential (same as starting potential) %BR%
#
#%SETUP%
#%END%
#

#%HISTORY%
#$Log: par263cyc1.mac,v $
#Revision 1.2  2012/05/14 15:03:17  claustre
#par263cycle now save data into SPECFILE
#
# modified 10/03/2009: include setE corrected CV %BR%
# modified 11/03/2009: calculate current, plot/print current vs. potential (not cts any more) %BR%
# modified 12/03/2009: include IGAIN %BR%
#
#%END%


#%IU%
#%MDESC%
def _par263cyc_plot(n,current_ranget,igaint) '{
    local short array x[n]
    local short array y[n]
    local short array dat[2][n]
    local       array datnew[1][n]
    local n_curve n_rd

    if(n>=3072){
        _par263_print(sprintf("%d higher than max 1024 allowed points",n), 1)
        exit
    }
 
    #Set current range (ugly solution), Geert
    if(current_ranget==-1) current_ranget=100000
    if(current_ranget==-2) current_ranget=10000
    if(current_ranget==-3) current_ranget=1000
    if(current_ranget==-4) current_ranget=100
    if(current_ranget==-5) current_ranget=10
    if(current_ranget==-6) current_ranget=1
 
    # Get I values (i.e. y axis)
    _par263_write(sprintf("BD 0 %d",n))
    n_rd = gpib_get(PAR263_ADDR,dat[1])
    if(n != n_rd) _par263_print("Error reading I values", 1);

    # Get U values (i.e. x axis)
    n_curve=1024*(int((n)/1024)+1)
    _par263_write(sprintf("BD %d %d",n_curve,n))
    n_rd = gpib_get(PAR263_ADDR,dat[0])
    if(n != n_rd) _par263_print("Error reading U values", 1);
 
    array_op("swap",dat)
 
    datnew=(-1*dat[1]*current_ranget/igaint)
 
    # init plotting device & plot
    plot_cntl("filter1,open")
    plot_cntl("erase")
    plot_cntl("lines")
    plot_range("auto","auto","auto","auto")
    plot_move(0,0,sprintf("CV I [nA] / E [mV], %d points",n))
    array_plot(dat[0][1:n-1],datnew[1:n-1])
}'

#%IU%
#%MDESC%
def _par263cyc_print(n,filena,cmd,init_pott,down_pott,up_pott,slopet,e_stept,current_ranget,igaint, cycles, cycle_num) '{ 
    local short array x[n]
    local short array y[n]
    local short array dat[2][n]
    local n_curve n_rd cmd
    local       array datnew[1][n]

    #Set current range (ugly solution), Geert
    if(current_ranget==-1) current_ranget=100000
    else if(current_ranget==-2) current_ranget=10000
    else if(current_ranget==-3) current_ranget=1000
    else if(current_ranget==-4) current_ranget=100
    else if(current_ranget==-5) current_ranget=10
    else if(current_ranget==-6) current_ranget=1

    # Get I values (i.e. y axis)
    _par263_write(sprintf("BD 0 %d",n))
    n_rd = gpib_get(PAR263_ADDR,dat[1])
    if(n != n_rd) _par263_print("Error reading I values", 1);

    # Get U values (i.e. x axis)
    n_curve=1024*(int((n)/1024)+1)
    _par263_write(sprintf("BD %d %d",n_curve,n))
    n_rd = gpib_get(PAR263_ADDR,dat[0])
    if(n != n_rd) _par263_print("Error reading U values", 1);

    array_op("swap",dat)
 
    datnew=-1*dat[1]*current_ranget/igaint #/1000 due to range of potentiostat, *1000 due to avoiding floating data (so current in nA
 
    # init plotting device & plot
    plot_cntl("filter1,open")
    plot_cntl("erase")
    plot_cntl("lines")
    plot_range("auto","auto","auto","auto")
    plot_move(0,0,sprintf("CV I [nA] / E [mV], %d points",n))
    array_plot(dat[0][1:n-1],datnew[1:n-1])
 
    # init saving procedure
    #if(filena==0){
    #    filena=getval("File name to dump I/E",cmd)} # for case of 1 cycle, ask for filename
    #on(filena);offt
    #print("#################################################\n# DATE " date())
    cmd = sprintf("par263cyc %d %d %d %d %d %d %d", init_pott, down_pott, up_pott, slopet, e_stept, cycles, current_ranget)
    fprintf(DATAFILE,"\n#S %d  %s\n#D %s\n",++SCAN_N,cmd,date())
    fprintf(DATAFILE, "#C cycle number = %d\n", cycle_num)
    fprintf(DATAFILE, "#C start pot %d mV, V1 %d mV, V2 %d mV, slope %d mV/s, step width %d mV/step, current range %d uA, IGAIN %d\n", init_pott, down_pott, up_pott, slopet, e_stept, current_ranget,igaint)
    fprintf(DATAFILE, "#L U/mV   I/cts   I/nA\n")
    array_dump(DATAFILE, dat,datnew)
    close(DATAFILE)
}' 

#%UU%
#%MDESC%
def par263cyc '{
    local init_pot up_pot final_pot down_pot slope ppsec
    local init_dac up_dac final_dac down_dac tmb
    local mr mr_cmd cmd
    local n1 n2 n3 points
    local filena
    local filemode __i
    
    if($# != 7) {
        p "Usage: $0 init_pot down_pot up_pot slope e_steps cycles current_range"
        p "   potentials are in mV"
        p "   slope in mV/second"
        p "   number of cycles"
        p "   current range [-1: 100 mA"
        p "                  -2:  10 mA"
        p "                  -3:   1 mA"
        p "                  -4: 100 muA"
        p "                  -5:  10 muA"
        p "                  -6:   1 muA"
        p "                  -7: 100 nA]"
        exit 
    }

    # Set MODULATION RESOLUTION to 2.5muV per count
    # mr = 0.0025 ; mr_cmd = 0 
    # Set MODULATION RESOLUTION to 25muV  per count
    # mr = 0.025  ; mr_cmd = 1 
    # Set MODULATION RESOLUTION to 250muV per count
    mr = 0.250  ; mr_cmd = 2 

    init_pot 		= $1
    down_pot 		= $2
    up_pot   		= $3
    slope    		= $4
    e_step	  	= $5
    cycles   		= $6
    current_range	= $7
    ppsec    		= slope/(e_step)
    spp      		= 1
    final_pot 		= init_pot
    if(ppsec<20) { 
			spp = 20/ppsec } 
 
    p "\n**********************************"
    p "starting potential = " init_pot
    p "upper vertex       = " up_pot
    p "lower vertex       = " down_pot
    p "end potential      = " final_pot

    down_pot1=down_pot
    up_pot1=up_pot
  
    gpib_put(PAR263_ADDR,"READE")
    tmp=gpib_get(PAR263_ADDR)
    sleep(0.1) 
    p "setE currently     = " tmp
    if(tmp!=0){
	init_pot=init_pot-tmp
 	down_pot=down_pot-tmp
 	up_pot=up_pot-tmp
	final_pot=init_pot
    }
 
    gpib_put(PAR263_ADDR,"IGAIN")
    igain=gpib_get(PAR263_ADDR)
    sleep(0.1) 
 
    if(cycles==0){exit}
    #cmd_name=sprintf("CV-%s-%d-%d-%d.dat",time(),down_pot1,up_pot1,slope) 
    if(cycles!=1){
        #check if there is a valid DATAFILE
        if (index(DATAFILE,"null")==0){
            _par263_print(sprintf("data will be dumped to SPECFILE: %s", DATAFILE))
        }else {
            _par263_print("SPECFILE is null, please set it using \"newfile\"", 1)
            exit
        }
        filena = DATAFILE
                    
    }
    else{filena=0}
 
    init_dac  = int(init_pot/mr)
    down_dac  = int(down_pot/mr)
    up_dac    = int(up_pot/mr)
    final_dac = int(final_pot/mr)
    tmb       = int(1000000/(ppsec*spp))

    if((init_dac>8000) || (init_dac<-8000)) {
        _par263_print( \
        sprintf("init_pot %dmV out of range +/-%dmV",init_pot,8000*mr), 1)
        exit
    }
    if((up_dac>8000) || (up_dac<-8000)) {
        _par263_print(sprintf("up_pot %dmV out of range +/-%dmV",up_pot,8000*mr), 1)
        exit
    }
    if((down_dac>8000) || (down_dac<-8000)) {
        _par263_print( \
        sprintf("down_pot %dmV out of range +/-%dmV",down_pot,8000*mr), 1)
        exit
    }
    if((slope>200) || (slope<1)) {
        _par263_print(sprintf("slope %dmV/s out of range [1,200]",slope), 1)
        exit
    }
    if((tmb>50000) || (tmb<400)) {
        _par263_print(sprintf("ppsec %d out of range [20,2500]",ppsec), 1)
        exit
    }

    # calculate the number of points of each slope
    n1=int(fabs(down_pot - init_pot)*(ppsec)/slope)
    n2=int(fabs(up_pot   - down_pot)*(ppsec)/slope)  + n1
    n3=int(fabs(up_pot   - final_pot)*(ppsec)/slope) + n2

    p "total \# points     = " n3
 
    # the number of points is fixed to 3072
    points=n3
    if(points>=3072) {
        _par263_print( \
        sprintf("too many points, decrease either E_step or increase slope",ppsec), 1)
        _par263_print(sprintf("n1=%d n2=%d n3=%d\n",n1,n2,n3), 1)
        exit
    }

    # Initializing Potentiostat
    _par263_write("27")
    #_par263_write("DCL") 			# No Default Parameters, since otherwise set E to 0 at beginning
    _par263_write("FLT 65") 		# Filter 65, means filter on I, but not on E (check manual for more details...
    _par263_write("SIE 3")			# Record I and E in parallel
    _par263_write("AR 0")			# Auto range off for I and E, AR makes problems for low currents...
    _par263_write("DCV 0")			# The destination CURVE is the 1st one
    _par263_write("PAM 0") 		# no averaging spp
    cmd=sprintf("S/P %d",spp)	
    _par263_write(cmd)				# set samples per point
    _par263_write("MM 1")			# Ramp modulation on (so using INITIAL and VERTEX)
    _par263_write("INTRP 1") 		# interpolation on (regarding samples per point) 
    cmd=sprintf("I/E %d",current_range)
    _par263_write(cmd)				# Set CURRENT TO VOLTAGE CONVERTER (as specified in input)
     cmd=sprintf("MR %d",mr_cmd)
    _par263_write(cmd)				# Set MODULATION RESOLUTION to 250muV per count
    cmd=sprintf("TMB %d",tmb) 
    _par263_write(cmd)				# Timeresolution
    cmd=sprintf("LP %d",points) 
    _par263_write(cmd)				# points=n3=total number of data points to get

    # setting up experiment
    cmd=sprintf("INITIAL  0   %d",init_dac) 
    _par263_write(cmd)				# set E to E_0 @ point 0
    cmd=sprintf("VERTEX %d %d",n1,down_dac)
    _par263_write(cmd)
    cmd=sprintf("VERTEX %d %d",n2,up_dac)
    _par263_write(cmd)
    cmd=sprintf("VERTEX %d %d",n3,final_dac)
    _par263_write(cmd)

    # Switch on the E on the CELL, if not already on
    _par263_write("CELL 1")
    _par263_write("P 1") #Pause for 1 sec

    # setting cycling loop
    for(__i=0;__i<cycles;__i++){
        _par263_write("NC")

        # Take curve
        _par263_write("TC")
        
        # Wait for the end of TC i.e. commands not treated
        p "\nWaiting curve to finish\t cycle "(__i+1)
        p "**********************************"

        while (_par263_waitcurve()) {
            printf("Data point: %d\t",PAR263_READ["lp"])
            printf("Current: ")
            _par263cyc_plot(points,current_range,igain)
            if (input(-1)=="q"){
	        _par263_write("HC")
	        SET=sprintf("SETE %d",tmp)
	        _par263_write("NC")
 	        _par263_write(SET) 
	        printf("CV aborted")
	        exit
            }
        }

        _par263cyc_print(points,filena,cmd_name,init_pot,down_pot,up_pot,slope,e_step,current_range,igain,cycles,__i)
    } 

    #gpib_put(PAR263_ADDR,"READE")
    #tmp=gpib_get(PAR263_ADDR)
    sleep(0.5) 
    SET=sprintf("SETE %d",tmp)
    _par263_write(SET) 
 
    #added by Francesco 2011-08-19:
    _par263_write("MM 0")			# set modulation off. If the MM is not set to 0 the ct command in the spec session will set the potential to an undesired value.
 
}'