From: David Schleef Date: Tue, 9 Oct 2001 23:45:16 +0000 (+0000) Subject: Split up comedi_calibrate.c, additional hacking X-Git-Tag: r0_7_17~16 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f3681b41fa10c58e9fe4eff2963c4dcb8dd0d11c;p=comedilib.git Split up comedi_calibrate.c, additional hacking --- diff --git a/comedi_calibrate/Makefile b/comedi_calibrate/Makefile index 4ec6ff5..49c0aee 100644 --- a/comedi_calibrate/Makefile +++ b/comedi_calibrate/Makefile @@ -7,11 +7,12 @@ LDFLAGS += -L../lib/ -lcomedi -lm BINS=comedi_calibrate +objs = comedi_calibrate.o ni.o all: $(BINS) -comedi_calibrate: comedi_calibrate.o - $(CC) -o comedi_calibrate comedi_calibrate.o $(LDFLAGS) +comedi_calibrate: $(objs) + $(CC) -o $@ $(objs) $(LDFLAGS) clean: -rm -f *.o $(BINS) diff --git a/comedi_calibrate/calib.h b/comedi_calibrate/calib.h new file mode 100644 index 0000000..897e1c0 --- /dev/null +++ b/comedi_calibrate/calib.h @@ -0,0 +1,181 @@ + +#ifndef __CALIB_H_ +#define __CALIB_H_ + +#include +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#define DPRINT(level,fmt,args...) do{if(verbose>=level)printf(fmt, ## args);}while(0) + +#define N_CALDACS 32 +#define N_OBSERVABLES 32 + +typedef struct{ + int subdev; + int chan; + + int maxdata; + int current; + + int type; + double gain; +}caldac; + +typedef struct{ + char *name; + + comedi_insn preobserve_insn; + lsampl_t preobserve_data; + + comedi_insn observe_insn; + + //comedi_range *range; + //int maxdata; + + double target; +}observable; + +extern caldac caldacs[N_CALDACS]; +extern int n_caldacs; + +extern observable observables[N_OBSERVABLES]; +extern int n_observables; + +extern comedi_t *dev; + +extern int ad_subdev; +extern int da_subdev; +extern int eeprom_subdev; +extern int caldac_subdev; + +extern char *devicename; +extern char *drivername; + +extern int verbose; + +enum { + STATUS_UNKNOWN = 0, + STATUS_GUESS, + STATUS_SOME, + STATUS_DONE +}; +extern int device_status; + +extern int do_output; + +/* high level */ + +void observe(void); +void preobserve(int obs); +void observable_dependence(int obs); +void measure_observable(int obs); +void reset_caldacs(void); + +/* drivers */ + +void ni_setup(void); + +/* low level */ + +void set_target(int obs,double target); +void update_caldac(int i); +void setup_caldacs(void); +void postgain_cal(int obs1, int obs2, int dac); +void cal1(int obs, int dac); + +/* misc and temp */ + +void channel_dependence(int adc,int range); +void caldac_dependence(int caldac); +void dump_curve(int adc,int caldac); +void chan_cal(int adc,int caldac,int range,double target); +int read_eeprom(int addr); + +double read_chan(int adc,int range); +int read_chan2(char *s,int adc,int range); +void set_ao(comedi_t *dev,int subdev,int chan,int range,double value); +void check_gain(int ad_chan,int range); +double check_gain_chan(int ad_chan,int range,int cdac); + +void (*do_cal)(void); +void cal_ni_results(void); + +/* helper functions */ + +int get_bipolar_lowgain(comedi_t *dev,int subdev); +int get_bipolar_highgain(comedi_t *dev,int subdev); +int get_unipolar_lowgain(comedi_t *dev,int subdev); + +/* printing scientific numbers */ + +int sci_sprint(char *s,double x,double y); +int sci_sprint_alt(char *s,double x,double y); + +/* linear fitting */ + +typedef struct { + int n; + + double *y_data; + double *yerr_data; + double *x_data; + + double x0; + double dx; + double yerr; + + /* stats */ + double s1,sx,sy,sxy,sxx; + + double min,max; + + /* results */ + double ave_x; + double ave_y; + double slope; + double err_slope; + double err_ave_y; + double S_min; + double dof; + +}linear_fit_t; +int linear_fit_monotonic(linear_fit_t *l); +double linear_fit_func_y(linear_fit_t *l,double x); +double check_gain_chan_x(linear_fit_t *l,unsigned int ad_chanspec,int cdac); + +/* slowly varying measurements */ + +typedef struct{ + comedi_t *dev; + + int maxdata; + int order; + int aref; + int range; + int subd; + int chan; + + comedi_range *rng; + + int n; + double average; + double stddev; + double error; +}new_sv_t; + +int new_sv_measure(new_sv_t *sv); +int new_sv_init(new_sv_t *sv,comedi_t *dev,int subdev,int chan,int range,int aref); + + +#endif + diff --git a/comedi_calibrate/comedi_calibrate.c b/comedi_calibrate/comedi_calibrate.c index 8414af8..c93e2d9 100644 --- a/comedi_calibrate/comedi_calibrate.c +++ b/comedi_calibrate/comedi_calibrate.c @@ -33,203 +33,38 @@ #include #include -#define DPRINT(level,fmt,args...) do{if(verbose>=level)printf(fmt, ## args);}while(0) +#include "calib.h" -#define N_CALDACS 32 -#define N_OBSERVABLES 32 +/* global variables */ -typedef struct{ - int subdev; - int chan; +caldac caldacs[N_CALDACS]; +int n_caldacs; - int maxdata; - int current; +observable observables[N_OBSERVABLES]; +int n_observables; - int type; - double gain; -}caldac; - -typedef struct{ - char *name; - - comedi_insn preobserve_insn; - lsampl_t preobserve_data; +comedi_t *dev; - comedi_insn observe_insn; - - //comedi_range *range; - //int maxdata; - - double target; -}observable; +int ad_subdev; +int da_subdev; +int eeprom_subdev; +int caldac_subdev; -static caldac caldacs[N_CALDACS]; -static observable observables[N_OBSERVABLES]; - -static int n_caldacs; -static int n_observables; - -static comedi_t *dev; - -static int ad_subdev; -static int da_subdev; -static int eeprom_subdev; -static int caldac_subdev; - -double read_chan(int adc,int range); -int read_chan2(char *s,int adc,int range); -void set_ao(comedi_t *dev,int subdev,int chan,int range,double value); -void check_gain(int ad_chan,int range); -double check_gain_chan(int ad_chan,int range,int cdac); +char *drivername = NULL; +char *devicename = NULL; int verbose = 0; -enum { - STATUS_UNKNOWN = 0, - STATUS_SOME, - STATUS_DONE -}; int device_status = STATUS_UNKNOWN; -/* tmep */ -void do_cal(void); - -void observe(void); -void preobserve(int obs); -void observable_dependence(int obs); -void measure_observable(int obs); -void ni_setup(void); -void set_target(int obs,double target); - -void cal_ni_results(void); - -void update_caldac(int i); -void reset_caldacs(void); -void setup_caldacs(void); -void cal_ni_mio_E(void); -void ni_mio_ai_postgain_cal(void); -void ni_mio_ai_postgain_cal_2(int chan,int dac,int range_lo,int range_hi,double gain); -void channel_dependence(int adc,int range); -void caldac_dependence(int caldac); -void dump_curve(int adc,int caldac); -void chan_cal(int adc,int caldac,int range,double target); -int read_eeprom(int addr); - -int get_bipolar_lowgain(comedi_t *dev,int subdev); -int get_bipolar_highgain(comedi_t *dev,int subdev); -int get_unipolar_lowgain(comedi_t *dev,int subdev); - -int sci_sprint(char *s,double x,double y); -int sci_sprint_alt(char *s,double x,double y); - - -typedef struct { - int n; - - double *y_data; - double *yerr_data; - double *x_data; - - double x0; - double dx; - double yerr; - - /* stats */ - double s1,sx,sy,sxy,sxx; - - double min,max; - - /* results */ - double ave_x; - double ave_y; - double slope; - double err_slope; - double err_ave_y; - double S_min; - double dof; - -}linear_fit_t; -int linear_fit_monotonic(linear_fit_t *l); -double linear_fit_func_y(linear_fit_t *l,double x); -double check_gain_chan_x(linear_fit_t *l,unsigned int ad_chanspec,int cdac); +/* */ -typedef struct{ - comedi_t *dev; - - int maxdata; - int order; - int aref; - int range; - int subd; - int chan; - - comedi_range *rng; - - int n; - double average; - double stddev; - double error; -}new_sv_t; - -int new_sv_measure(new_sv_t *sv); -int new_sv_init(new_sv_t *sv,comedi_t *dev,int subdev,int chan,int range,int aref); struct board_struct{ char *name; void (*setup)(void); }; -#if 0 -void cal_ni_16e_1(void); -void cal_ni_16e_10(void); -void cal_ni_16xe_50(void); -void cal_ni_16xe_10(void); -void cal_ni_6023e(void); -void cal_ni_6071e(void); -void cal_ni_daqcard_ai_16xe_50(void); -void cal_ni_unknown(void); - -struct board_struct boards[]={ - { "at-mio-16e-1", cal_ni_16e_1 }, - { "at-mio-16e-2", cal_ni_16e_1 }, - { "at-mio-16e-10", cal_ni_16e_10 }, -// { "at-mio-16de-10", cal_ni_unknown }, - { "at-mio-64e-3", cal_ni_16e_1 }, -// { "at-mio-16xe-50", cal_ni_unknown }, -// { "at-mio-16xe-10", cal_ni_unknown }, -// { "at-ai-16xe-10", cal_ni_unknown }, - { "pci-mio-16xe-50", cal_ni_16xe_50 }, - { "pci-mio-16xe-10", cal_ni_16xe_10 }, -// { "pxi-6030e", cal_ni_unknown }, - { "pci-mio-16e-1", cal_ni_16e_1 }, -// { "pci-mio-16e-4", cal_ni_unknown }, -// { "pxi-6040e", cal_ni_unknown }, -// { "pci-6031e", cal_ni_unknown }, -// { "pci-6032e", cal_ni_unknown }, -// { "pci-6033e", cal_ni_unknown }, -// { "pci-6071e", cal_ni_unknown }, - { "pci-6023e", cal_ni_6023e }, - { "pci-6024e", cal_ni_6023e }, // guess - { "pci-6025e", cal_ni_6023e }, // guess - { "pxi-6025e", cal_ni_6023e }, // guess - { "pci-6034e", cal_ni_6023e }, // guess - { "pci-6035e", cal_ni_6023e }, -// { "pci-6052e", cal_ni_unknown }, -// { "pci-6110e", cal_ni_unknown }, -// { "pci-6111e", cal_ni_unknown }, -// { "pci-6711", cal_ni_unknown }, -// { "pci-6713", cal_ni_unknown }, - { "pxi-6071e", cal_ni_6071e }, -// { "pxi-6070e", cal_ni_unknown }, -// { "pxi-6052e", cal_ni_unknown }, - { "DAQCard-ai-16xe-50", cal_ni_daqcard_ai_16xe_50 }, -// { "DAQCard-ai-16e-4", cal_ni_unknown }, -// { "DAQCard-6062e", cal_ni_unknown }, -// { "DAQCard-6024e", cal_ni_unknown }, -}; -#define n_boards (sizeof(boards)/sizeof(boards[0])) -#endif - struct board_struct drivers[] = { { "ni_pcimio", ni_setup }, { "ni_atmio", ni_setup }, @@ -240,7 +75,7 @@ struct board_struct drivers[] = { int do_dump = 0; int do_reset = 1; int do_calibrate = 1; -int do_results = 1; +int do_results = 0; int do_output = 1; struct option options[] = { @@ -257,6 +92,8 @@ struct option options[] = { { "no-dump", 0, &do_dump, 0 }, { "results", 0, &do_results, 1 }, { "no-results", 0, &do_results, 0 }, + { "output", 0, &do_output, 1 }, + { "no-output", 0, &do_output, 0 }, { 0 }, }; @@ -264,8 +101,6 @@ int main(int argc, char *argv[]) { char *fn = NULL; int c; - char *drivername = NULL; - char *devicename = NULL; int i; struct board_struct *this_board; int index; @@ -353,147 +188,12 @@ ok: if(do_reset)reset_caldacs(); if(do_dump)observe(); - if(do_calibrate)do_cal(); + if(do_calibrate && do_cal)do_cal(); if(do_results)observe(); return 0; } -enum { - ni_zero_offset_low = 0, - ni_zero_offset_high, - ni_reference_low, - ni_unip_offset_low, - ni_ao0_zero_offset, - ni_ao0_reference, - ni_ao1_zero_offset, - ni_ao1_reference, -}; - -void ni_setup(void) -{ - comedi_insn tmpl; - int bipolar_lowgain; - int bipolar_highgain; - int unipolar_lowgain; - double voltage_reference; - observable *o; - - bipolar_lowgain = get_bipolar_lowgain(dev,ad_subdev); - bipolar_highgain = get_bipolar_highgain(dev,ad_subdev); - unipolar_lowgain = get_unipolar_lowgain(dev,ad_subdev); - - voltage_reference = 5.000; - - memset(&tmpl,0,sizeof(tmpl)); - tmpl.insn = INSN_READ; - tmpl.n = 1; - tmpl.subdev = ad_subdev; - - /* 0 offset, low gain */ - o = observables + ni_zero_offset_low; - o->name = "ai, bipolar zero offset, low gain"; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK(0,bipolar_lowgain,AREF_OTHER); - o->target = 0; - - /* 0 offset, high gain */ - o = observables + ni_zero_offset_high; - o->name = "ai, bipolar zero offset, high gain"; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK(0,bipolar_highgain,AREF_OTHER); - o->target = 0; - - /* voltage reference */ - o = observables + ni_reference_low; - o->name = "ai, bipolar voltage reference, low gain"; - o->observe_insn = tmpl; - o->observe_insn.chanspec = CR_PACK(5,bipolar_lowgain,AREF_OTHER); - o->target = voltage_reference; - - if(unipolar_lowgain>=0){ - /* unip/bip offset */ - o = observables + ni_unip_offset_low; - o->name = "ai, unipolar zero offset, low gain"; - o->observe_insn = tmpl; - o->observe_insn.chanspec = - CR_PACK(0,unipolar_lowgain,AREF_OTHER); - o->target = 0; - -#if 0 - /* unip gain */ - o = observables + ni_unip_reference_low; - o->name = "ai, unipolar voltage reference, low gain"; - o->observe_insn = tmpl; - o->observe_insn.chanspec = - CR_PACK(5,unipolar_lowgain,AREF_OTHER); - o->target = voltage_reference; - i++; -#endif - } - - if(da_subdev>=0){ - comedi_insn po_tmpl; - - memset(&po_tmpl,0,sizeof(po_tmpl)); - po_tmpl.insn = INSN_WRITE; - po_tmpl.n = 1; - po_tmpl.subdev = da_subdev; - - /* ao 0, zero offset */ - o = observables + ni_ao0_zero_offset; - o->name = "ao 0, zero offset, low gain"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK(0,0,0); - o->preobserve_insn.data = &o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = - CR_PACK(2,bipolar_lowgain,AREF_OTHER); - set_target(ni_ao0_zero_offset,0.0); - - /* ao 0, gain */ - o = observables + ni_ao0_reference; - o->name = "ao 0, reference voltage, low gain"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK(0,0,0); - o->preobserve_insn.data = &o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = - CR_PACK(6,bipolar_lowgain,AREF_OTHER); - set_target(ni_ao0_reference,5.0); - o->target -= voltage_reference; - - /* ao 1, zero offset */ - o = observables + ni_ao1_zero_offset; - o->name = "ao 1, zero offset, low gain"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK(1,0,0); - o->preobserve_insn.data = &o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = - CR_PACK(3,bipolar_lowgain,AREF_OTHER); - set_target(ni_ao1_zero_offset,0.0); - - /* ao 1, gain */ - o = observables + ni_ao1_reference; - o->name = "ao 1, reference voltage, low gain"; - o->preobserve_insn = po_tmpl; - o->preobserve_insn.chanspec = CR_PACK(1,0,0); - o->preobserve_insn.data = &o->preobserve_data; - o->observe_insn = tmpl; - o->observe_insn.chanspec = - CR_PACK(7,bipolar_lowgain,AREF_OTHER); - set_target(ni_ao1_reference,5.0); - o->target -= voltage_reference; - - } - n_observables = ni_ao1_reference + 1; - - setup_caldacs(); - - -} - void set_target(int obs,double target) { comedi_range *range; @@ -641,264 +341,6 @@ void cal1(int obs, int dac) } } -void do_cal(void) -{ -#if 0 - // daqcard - postgain_cal(ni_zero_offset_low,ni_zero_offset_high,2); - cal1(ni_zero_offset_high,8); - cal1(ni_reference_low,0); -#endif - - // 16e-2 - postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); - cal1(ni_zero_offset_high,0); - cal1(ni_reference_low,3); - cal1(ni_unip_offset_low,2); - if(do_output){ - cal1(ni_ao0_zero_offset,5); - cal1(ni_ao0_reference,6); - cal1(ni_ao1_zero_offset,8); - cal1(ni_ao1_reference,9); - } - -#if 0 - // 16e-10 (old) - postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); - cal1(ni_zero_offset_high,10); - cal1(ni_zero_offset_high,0); - cal1(ni_reference_low,3); - cal1(ni_unip_offset_low,2); - if(do_output){ - cal1(ni_ao0_zero_offset,5); // guess - cal1(ni_ao0_reference,6); // guess - cal1(ni_ao0_zero_offset,8); // guess - cal1(ni_ao0_reference,9); // guess - } -#endif - -#if 0 - // 16xe-50 (old) (same as daqcard?) - postgain_cal(ni_zero_offset_low,ni_zero_offset_high,2); - cal1(ni_zero_offset_high,8); - cal1(ni_reference_low,0); - if(do_output){ - // unknown - } -#endif - -#if 0 - // 6035e (old) - postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); - cal1(ni_zero_offset_high,0); - cal1(ni_reference_low,3); - if(do_output){ - // unknown - } -#endif - -#if 0 - // 6071e (old) - postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); - cal1(ni_zero_offset_high,0); - cal1(ni_reference_low,3); - if(do_output){ - // unknown - } -#endif -} - - -double ni_get_reference(int lsb_loc,int msb_loc) -{ - int lsb,msb; - int uv; - double ref; - - lsb=read_eeprom(lsb_loc); - msb=read_eeprom(msb_loc); - printf("lsb=%d msb=%d\n",read_eeprom(425),read_eeprom(426)); - - uv=lsb | (msb<<8); - if(uv>=0x8000)uv-=0x10000; - ref=5.000+1.0e-6*uv; - printf("ref=%g\n",ref); - - return ref; -} - -void cal_ni_unknown(void) -{ - comedi_range *range; - int bipolar_lowgain; - int bipolar_highgain; - int unipolar_lowgain; - int have_ao = 1; - - reset_caldacs(); - printf("Warning: device not calibrated due to insufficient information\n"); - printf("Please send this output to \n"); - printf("$Id$\n"); - printf("Device name: %s\n",comedi_get_board_name(dev)); - printf("Comedi version: %d.%d.%d\n", - (comedi_get_version_code(dev)>>16)&0xff, - (comedi_get_version_code(dev)>>8)&0xff, - (comedi_get_version_code(dev))&0xff); - - bipolar_lowgain = get_bipolar_lowgain(dev,ad_subdev); - bipolar_highgain = get_bipolar_highgain(dev,ad_subdev); - unipolar_lowgain = get_unipolar_lowgain(dev,ad_subdev); - - /* 0 offset, low gain */ - range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - DPRINT(0,"bipolar zero offset, low gain [%g,%g]\n", - range->min,range->max); - channel_dependence(0,bipolar_lowgain); - - /* 0 offset, high gain */ - range = comedi_get_range(dev,ad_subdev,0,bipolar_highgain); - DPRINT(0,"bipolar zero offset, high gain [%g,%g]\n", - range->min,range->max); - channel_dependence(0,bipolar_highgain); - - /* unip/bip offset */ - range = comedi_get_range(dev,ad_subdev,0,unipolar_lowgain); - DPRINT(0,"unipolar zero offset, low gain [%g,%g]\n", - range->min,range->max); - channel_dependence(0,unipolar_lowgain); - - /* voltage reference */ - range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - DPRINT(0,"bipolar voltage reference, low gain [%g,%g]\n", - range->min,range->max); - channel_dependence(5,bipolar_lowgain); - - have_ao = (comedi_get_subdevice_type(dev,da_subdev)==COMEDI_SUBD_AO); - if(have_ao){ - int ao_chan; - - /* ao 0, zero offset */ - ao_chan = 0; - set_ao(dev,da_subdev,ao_chan,0,0.0); - range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - DPRINT(0,"ao 0, zero offset, low gain [%g,%g]\n", - range->min,range->max); - channel_dependence(2,bipolar_lowgain); - - /* ao 0, gain */ - ao_chan = 0; - set_ao(dev,da_subdev,ao_chan,0,5.0); - range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - DPRINT(0,"ao 0, gain, low gain [%g,%g]\n", - range->min,range->max); - channel_dependence(6,bipolar_lowgain); - - /* ao 1, zero offset */ - ao_chan = 1; - set_ao(dev,da_subdev,ao_chan,0,0.0); - range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - DPRINT(0,"ao 1, zero offset, low gain [%g,%g]\n", - range->min,range->max); - channel_dependence(3,bipolar_lowgain); - - /* ao 1, gain */ - ao_chan = 1; - set_ao(dev,da_subdev,ao_chan,0,5.0); - range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - DPRINT(0,"ao 1, gain, low gain [%g,%g]\n", - range->min,range->max); - channel_dependence(7,bipolar_lowgain); - } - - cal_ni_results(); -} - -void cal_ni_results(void) -{ - comedi_range *range; - int bipolar_lowgain; - int bipolar_highgain; - int unipolar_lowgain; - //int have_ao; - char s[32]; - - bipolar_lowgain = get_bipolar_lowgain(dev,ad_subdev); - bipolar_highgain = get_bipolar_highgain(dev,ad_subdev); - unipolar_lowgain = get_unipolar_lowgain(dev,ad_subdev); - - /* 0 offset, low gain */ - range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); - read_chan2(s,0,bipolar_lowgain); - DPRINT(0,"bipolar zero offset, low gain [%g,%g]: %s\n", - range->min,range->max,s); - - /* 0 offset, high gain */ - range = comedi_get_range(dev,ad_subdev,0,bipolar_highgain); - read_chan2(s,0,bipolar_highgain); - DPRINT(0,"bipolar zero offset, high gain [%g,%g]: %s\n", - range->min,range->max,s); - - /* unip/bip offset */ - range = comedi_get_range(dev,ad_subdev,0,unipolar_lowgain); - read_chan2(s,0,unipolar_lowgain); - DPRINT(0,"unipolar zero offset, low gain [%g,%g]: %s\n", - range->min,range->max,s); - -} - -void ni_mio_ai_postgain_cal(void) -{ - linear_fit_t l; - double offset_r0; - double offset_r7; - double gain; - double a; - - check_gain_chan_x(&l,CR_PACK(0,0,AREF_OTHER),1); - offset_r0=linear_fit_func_y(&l,caldacs[1].current); - printf("offset r0 %g\n",offset_r0); - - check_gain_chan_x(&l,CR_PACK(0,7,AREF_OTHER),1); - offset_r7=linear_fit_func_y(&l,caldacs[1].current); - printf("offset r7 %g\n",offset_r7); - - gain=l.slope; - - a=(offset_r0-offset_r7)/(200.0-1.0); - a=caldacs[1].current-a/gain; - - printf("%g\n",a); - - caldacs[1].current=rint(a); - update_caldac(1); -} - -void ni_mio_ai_postgain_cal_2(int chan,int dac,int range_lo,int range_hi,double gain) -{ - double offset_lo,offset_hi; - linear_fit_t l; - double slope; - double a; - - check_gain_chan_x(&l,CR_PACK(chan,range_lo,AREF_OTHER),dac); - offset_lo=linear_fit_func_y(&l,caldacs[dac].current); - printf("offset lo %g\n",offset_lo); - - check_gain_chan_x(&l,CR_PACK(chan,range_hi,AREF_OTHER),dac); - offset_hi=linear_fit_func_y(&l,caldacs[dac].current); - printf("offset hi %g\n",offset_hi); - - slope=l.slope; - - a=(offset_lo-offset_hi)/(gain-1.0); - a=caldacs[dac].current-a/slope; - - printf("%g\n",a); - - caldacs[dac].current=rint(a); - update_caldac(dac); -} - void chan_cal(int adc,int cdac,int range,double target) { linear_fit_t l; diff --git a/comedi_calibrate/ni.c b/comedi_calibrate/ni.c new file mode 100644 index 0000000..f5ae51b --- /dev/null +++ b/comedi_calibrate/ni.c @@ -0,0 +1,515 @@ +/* + A little auto-calibration utility, for boards + that support it. + + Right now, it only supports NI E series boards, + but it should be easily portable. + + A few things need improvement here: + - current system gets "close", but doesn't + do any fine-tuning + - no pre/post gain discrimination for the + A/D zero offset. + - should read (and use) the actual reference + voltage value from eeprom + - statistics would be nice, to show how good + the calibration is. + - doesn't check unipolar ranges + - "alternate calibrations" would be cool--to + accurately measure 0 in a unipolar range + - more portable + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "calib.h" + + +struct board_struct{ + char *name; + int status; + void (*cal)(void); +}; + +void ni_setup_board(void); +void ni_setup_observables(void); + +void cal_ni_16e_1(void); +void cal_ni_daqcard_ai_16xe_50(void); +void cal_ni_6035e(void); +void cal_ni_6071e(void); +void cal_ni_16e_10(void); +void cal_ni_16xe_50(void); + +struct board_struct boards[]={ + { "at-mio-16e-2", STATUS_DONE, cal_ni_16e_1 }, + { "DAQCard-ai-16xe-50", STATUS_DONE, cal_ni_daqcard_ai_16xe_50 }, + { "at-mio-16e-1", STATUS_SOME, cal_ni_16e_1 }, + { "pci-mio-16e-1", STATUS_SOME, cal_ni_16e_1 }, + { "pci-6035e", STATUS_GUESS, cal_ni_6035e }, + { "pci-6071e", STATUS_GUESS, cal_ni_6071e }, + { "pxi-6071e", STATUS_GUESS, cal_ni_6071e }, + { "at-mio-16e-10", STATUS_GUESS, cal_ni_16e_10 }, + { "pci-mio-16xe-50", STATUS_GUESS, cal_ni_16xe_50 }, + { "pci-6023e", STATUS_GUESS, cal_ni_6035e }, +#if 0 +// { "at-mio-16de-10", cal_ni_unknown }, + { "at-mio-64e-3", cal_ni_16e_1 }, +// { "at-mio-16xe-50", cal_ni_unknown }, +// { "at-mio-16xe-10", cal_ni_unknown }, +// { "at-ai-16xe-10", cal_ni_unknown }, + { "pci-mio-16xe-10", cal_ni_16xe_10 }, +// { "pxi-6030e", cal_ni_unknown }, +// { "pci-mio-16e-4", cal_ni_unknown }, +// { "pxi-6040e", cal_ni_unknown }, +// { "pci-6031e", cal_ni_unknown }, +// { "pci-6032e", cal_ni_unknown }, +// { "pci-6033e", cal_ni_unknown }, +// { "pci-6071e", cal_ni_unknown }, + { "pci-6024e", cal_ni_6023e }, // guess + { "pci-6025e", cal_ni_6023e }, // guess + { "pxi-6025e", cal_ni_6023e }, // guess + { "pci-6034e", cal_ni_6023e }, // guess + { "pci-6035e", cal_ni_6023e }, +// { "pci-6052e", cal_ni_unknown }, +// { "pci-6110e", cal_ni_unknown }, +// { "pci-6111e", cal_ni_unknown }, +// { "pci-6711", cal_ni_unknown }, +// { "pci-6713", cal_ni_unknown }, +// { "pxi-6070e", cal_ni_unknown }, +// { "pxi-6052e", cal_ni_unknown }, +// { "DAQCard-ai-16e-4", cal_ni_unknown }, +// { "DAQCard-6062e", cal_ni_unknown }, +// { "DAQCard-6024e", cal_ni_unknown }, +#endif +}; +#define n_boards (sizeof(boards)/sizeof(boards[0])) + +enum { + ni_zero_offset_low = 0, + ni_zero_offset_high, + ni_reference_low, + ni_unip_offset_low, + ni_ao0_zero_offset, + ni_ao0_reference, + ni_ao1_zero_offset, + ni_ao1_reference, +}; + +void ni_setup(void) +{ + ni_setup_board(); + ni_setup_observables(); + setup_caldacs(); +} + +void ni_setup_board(void) +{ + int i; + + for(i=0;iname = "ai, bipolar zero offset, low gain"; + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK(0,bipolar_lowgain,AREF_OTHER); + o->target = 0; + + /* 0 offset, high gain */ + o = observables + ni_zero_offset_high; + o->name = "ai, bipolar zero offset, high gain"; + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK(0,bipolar_highgain,AREF_OTHER); + o->target = 0; + + /* voltage reference */ + o = observables + ni_reference_low; + o->name = "ai, bipolar voltage reference, low gain"; + o->observe_insn = tmpl; + o->observe_insn.chanspec = CR_PACK(5,bipolar_lowgain,AREF_OTHER); + o->target = voltage_reference; + + if(unipolar_lowgain>=0){ + /* unip/bip offset */ + o = observables + ni_unip_offset_low; + o->name = "ai, unipolar zero offset, low gain"; + o->observe_insn = tmpl; + o->observe_insn.chanspec = + CR_PACK(0,unipolar_lowgain,AREF_OTHER); + o->target = 0; + +#if 0 + /* unip gain */ + o = observables + ni_unip_reference_low; + o->name = "ai, unipolar voltage reference, low gain"; + o->observe_insn = tmpl; + o->observe_insn.chanspec = + CR_PACK(5,unipolar_lowgain,AREF_OTHER); + o->target = voltage_reference; + i++; +#endif + } + + if(da_subdev>=0){ + comedi_insn po_tmpl; + + memset(&po_tmpl,0,sizeof(po_tmpl)); + po_tmpl.insn = INSN_WRITE; + po_tmpl.n = 1; + po_tmpl.subdev = da_subdev; + + /* ao 0, zero offset */ + o = observables + ni_ao0_zero_offset; + o->name = "ao 0, zero offset, low gain"; + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK(0,0,0); + o->preobserve_insn.data = &o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = + CR_PACK(2,bipolar_lowgain,AREF_OTHER); + set_target(ni_ao0_zero_offset,0.0); + + /* ao 0, gain */ + o = observables + ni_ao0_reference; + o->name = "ao 0, reference voltage, low gain"; + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK(0,0,0); + o->preobserve_insn.data = &o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = + CR_PACK(6,bipolar_lowgain,AREF_OTHER); + set_target(ni_ao0_reference,5.0); + o->target -= voltage_reference; + + /* ao 1, zero offset */ + o = observables + ni_ao1_zero_offset; + o->name = "ao 1, zero offset, low gain"; + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK(1,0,0); + o->preobserve_insn.data = &o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = + CR_PACK(3,bipolar_lowgain,AREF_OTHER); + set_target(ni_ao1_zero_offset,0.0); + + /* ao 1, gain */ + o = observables + ni_ao1_reference; + o->name = "ao 1, reference voltage, low gain"; + o->preobserve_insn = po_tmpl; + o->preobserve_insn.chanspec = CR_PACK(1,0,0); + o->preobserve_insn.data = &o->preobserve_data; + o->observe_insn = tmpl; + o->observe_insn.chanspec = + CR_PACK(7,bipolar_lowgain,AREF_OTHER); + set_target(ni_ao1_reference,5.0); + o->target -= voltage_reference; + + } + n_observables = ni_ao1_reference + 1; +} + +void cal_ni_daqcard_ai_16xe_50(void) +{ + // daqcard + postgain_cal(ni_zero_offset_low,ni_zero_offset_high,2); + cal1(ni_zero_offset_high,8); + cal1(ni_reference_low,0); +} + +void cal_ni_16e_1(void) +{ + // 16e-2 + postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); + cal1(ni_zero_offset_high,0); + cal1(ni_reference_low,3); + cal1(ni_unip_offset_low,2); + if(do_output){ + cal1(ni_ao0_zero_offset,5); + cal1(ni_ao0_reference,6); + cal1(ni_ao1_zero_offset,8); + cal1(ni_ao1_reference,9); + } +} + +void cal_ni_16e_10(void) +{ + // 16e-10 (old) + postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); + cal1(ni_zero_offset_high,10); + cal1(ni_zero_offset_high,0); + cal1(ni_reference_low,3); + cal1(ni_unip_offset_low,2); + if(do_output){ + cal1(ni_ao0_zero_offset,5); // guess + cal1(ni_ao0_reference,6); // guess + cal1(ni_ao0_zero_offset,8); // guess + cal1(ni_ao0_reference,9); // guess + } +} + +void cal_ni_16xe_50(void) +{ + // 16xe-50 (old) (same as daqcard?) + postgain_cal(ni_zero_offset_low,ni_zero_offset_high,2); + cal1(ni_zero_offset_high,8); + cal1(ni_reference_low,0); + if(do_output){ + // unknown + } +} + +void cal_ni_6035e(void) +{ + // 6035e (old) + postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); + cal1(ni_zero_offset_high,0); + cal1(ni_reference_low,3); + if(do_output){ + // unknown + } +} + +void cal_ni_6071e(void) +{ + // 6071e (old) + postgain_cal(ni_zero_offset_low,ni_zero_offset_high,1); + cal1(ni_zero_offset_high,0); + cal1(ni_reference_low,3); + if(do_output){ + // unknown + } +} + + +double ni_get_reference(int lsb_loc,int msb_loc) +{ + int lsb,msb; + int uv; + double ref; + + lsb=read_eeprom(lsb_loc); + msb=read_eeprom(msb_loc); + printf("lsb=%d msb=%d\n",read_eeprom(425),read_eeprom(426)); + + uv=lsb | (msb<<8); + if(uv>=0x8000)uv-=0x10000; + ref=5.000+1.0e-6*uv; + printf("ref=%g\n",ref); + + return ref; +} + +void cal_ni_unknown(void) +{ + comedi_range *range; + int bipolar_lowgain; + int bipolar_highgain; + int unipolar_lowgain; + int have_ao = 1; + + reset_caldacs(); + printf("Warning: device not calibrated due to insufficient information\n"); + printf("Please send this output to \n"); + printf("$Id$\n"); + printf("Device name: %s\n",comedi_get_board_name(dev)); + printf("Comedi version: %d.%d.%d\n", + (comedi_get_version_code(dev)>>16)&0xff, + (comedi_get_version_code(dev)>>8)&0xff, + (comedi_get_version_code(dev))&0xff); + + bipolar_lowgain = get_bipolar_lowgain(dev,ad_subdev); + bipolar_highgain = get_bipolar_highgain(dev,ad_subdev); + unipolar_lowgain = get_unipolar_lowgain(dev,ad_subdev); + + /* 0 offset, low gain */ + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"bipolar zero offset, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(0,bipolar_lowgain); + + /* 0 offset, high gain */ + range = comedi_get_range(dev,ad_subdev,0,bipolar_highgain); + DPRINT(0,"bipolar zero offset, high gain [%g,%g]\n", + range->min,range->max); + channel_dependence(0,bipolar_highgain); + + /* unip/bip offset */ + range = comedi_get_range(dev,ad_subdev,0,unipolar_lowgain); + DPRINT(0,"unipolar zero offset, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(0,unipolar_lowgain); + + /* voltage reference */ + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"bipolar voltage reference, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(5,bipolar_lowgain); + + have_ao = (comedi_get_subdevice_type(dev,da_subdev)==COMEDI_SUBD_AO); + if(have_ao){ + int ao_chan; + + /* ao 0, zero offset */ + ao_chan = 0; + set_ao(dev,da_subdev,ao_chan,0,0.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 0, zero offset, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(2,bipolar_lowgain); + + /* ao 0, gain */ + ao_chan = 0; + set_ao(dev,da_subdev,ao_chan,0,5.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 0, gain, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(6,bipolar_lowgain); + + /* ao 1, zero offset */ + ao_chan = 1; + set_ao(dev,da_subdev,ao_chan,0,0.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 1, zero offset, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(3,bipolar_lowgain); + + /* ao 1, gain */ + ao_chan = 1; + set_ao(dev,da_subdev,ao_chan,0,5.0); + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + DPRINT(0,"ao 1, gain, low gain [%g,%g]\n", + range->min,range->max); + channel_dependence(7,bipolar_lowgain); + } + + cal_ni_results(); +} + +void cal_ni_results(void) +{ + comedi_range *range; + int bipolar_lowgain; + int bipolar_highgain; + int unipolar_lowgain; + //int have_ao; + char s[32]; + + bipolar_lowgain = get_bipolar_lowgain(dev,ad_subdev); + bipolar_highgain = get_bipolar_highgain(dev,ad_subdev); + unipolar_lowgain = get_unipolar_lowgain(dev,ad_subdev); + + /* 0 offset, low gain */ + range = comedi_get_range(dev,ad_subdev,0,bipolar_lowgain); + read_chan2(s,0,bipolar_lowgain); + DPRINT(0,"bipolar zero offset, low gain [%g,%g]: %s\n", + range->min,range->max,s); + + /* 0 offset, high gain */ + range = comedi_get_range(dev,ad_subdev,0,bipolar_highgain); + read_chan2(s,0,bipolar_highgain); + DPRINT(0,"bipolar zero offset, high gain [%g,%g]: %s\n", + range->min,range->max,s); + + /* unip/bip offset */ + range = comedi_get_range(dev,ad_subdev,0,unipolar_lowgain); + read_chan2(s,0,unipolar_lowgain); + DPRINT(0,"unipolar zero offset, low gain [%g,%g]: %s\n", + range->min,range->max,s); + +} + +#if 0 +void ni_mio_ai_postgain_cal(void) +{ + linear_fit_t l; + double offset_r0; + double offset_r7; + double gain; + double a; + + check_gain_chan_x(&l,CR_PACK(0,0,AREF_OTHER),1); + offset_r0=linear_fit_func_y(&l,caldacs[1].current); + printf("offset r0 %g\n",offset_r0); + + check_gain_chan_x(&l,CR_PACK(0,7,AREF_OTHER),1); + offset_r7=linear_fit_func_y(&l,caldacs[1].current); + printf("offset r7 %g\n",offset_r7); + + gain=l.slope; + + a=(offset_r0-offset_r7)/(200.0-1.0); + a=caldacs[1].current-a/gain; + + printf("%g\n",a); + + caldacs[1].current=rint(a); + update_caldac(1); +} + +void ni_mio_ai_postgain_cal_2(int chan,int dac,int range_lo,int range_hi,double gain) +{ + double offset_lo,offset_hi; + linear_fit_t l; + double slope; + double a; + + check_gain_chan_x(&l,CR_PACK(chan,range_lo,AREF_OTHER),dac); + offset_lo=linear_fit_func_y(&l,caldacs[dac].current); + printf("offset lo %g\n",offset_lo); + + check_gain_chan_x(&l,CR_PACK(chan,range_hi,AREF_OTHER),dac); + offset_hi=linear_fit_func_y(&l,caldacs[dac].current); + printf("offset hi %g\n",offset_hi); + + slope=l.slope; + + a=(offset_lo-offset_hi)/(gain-1.0); + a=caldacs[dac].current-a/slope; + + printf("%g\n",a); + + caldacs[dac].current=rint(a); + update_caldac(dac); +} +#endif +