Commit f6c2c781 authored by Achim Morschhauser's avatar Achim Morschhauser
Browse files

Automatically adapt full-scale value for calibration

- Modify the calibration constants to include the fullscale value
  (M=40 for manual calibration; M=42.5 for self-calibration)
- Allow different channels with different calibration method
- Read calibration mode and temperature from saved calibration
parent b41d5ed0
......@@ -46,13 +46,6 @@ private:
/** Map containing the ADC calibration key-value pairs */
std::unordered_map<std::string, struct adc_cal> map_ADC;
/** ADC Offsets */
std::vector<int> adc_offset;
/** ADC scale values */
std::vector<int> adc_scale;
/** ADC configuration */
std::vector<int> adc_config;
//
// Constructors
//
......@@ -75,9 +68,19 @@ public:
/** Calibrate data */
int calibrate(data_obs *sdata);
/** Multiply the calibration scale values for data **/
int multiply_scale(std::vector<double> &scale, int pos=0);
/** Get the calibration constants for data **/
int get_calibration(std::vector<double> &offset,
std::vector<double> &scale);
/** Get the calibration constants for the ADC */
int get_adc_calibrate(std::string config, std::string &offset,
std::string &scale);
std::string &scale, std::string &mode);
/** Get the calibration constants for the ADC (with temperature) */
int get_adc_calibrate(std::string config, std::string &offset,
std::string &scale, std::string &mode, double &temperature);
/** Add a calibration constant for the ADC */
int add_adc_calibrate(std::string config, std::string offset,
......
......@@ -50,10 +50,6 @@ int quartz_freq;
/** The serial number */
std::string sn;
/** The conversion constant */
//TODO Should be an array of three!
double M;
/** Digital filter output rates */
double valid_filter_rates[11];
static const int valid_filter_rates_num=11;
......@@ -177,7 +173,7 @@ int init();
int init_run(double freq);
/** General calibration routine for all three channels*/
int calibrate(int repeat, std::string mode, double &fullscale);
int calibrate(int repeat, std::string mode);
int calibrate_channel(int channel, int repeat, std::string mode, std::string config);
/** Set calibration on the ObsDAQ*/
int set_calibration(int channel, std::string &adc_offset,
......
......@@ -5,6 +5,7 @@
#include <fstream> // File operations
#include <unordered_map>
#include <iomanip> // Set precision in strstream
#include <algorithm> // min/max functions
#include <Obs_Calibration_Vector.hpp>
#include <stdio.h>
......@@ -40,17 +41,12 @@ Obs_Calibration_Vector::Obs_Calibration_Vector(std::vector<double> &offset,
// Set size and replace
this->offset = offset;
this->scale = scale;
int i = 0;
while (do_cal == 0 && i < N) {
if (offset[i] != 0)
;
do_cal = 1;
if (scale[i] != 1)
;
do_cal = 1;
if (offset[i] != 0) do_cal = 1;
if (scale[i] != 1) do_cal = 1;
}
}
......@@ -96,13 +92,62 @@ int Obs_Calibration_Vector::calibrate(data_obs *data) {
}
/****************************************************************************
*
* Get the calibration constants for data
*
***************************************************************************/
int Obs_Calibration_Vector::get_calibration(std::vector<double> &offset,
std::vector<double> &scale){
}
/****************************************************************************
*
* Multiply the scale values for data calibration
*
***************************************************************************/
int Obs_Calibration_Vector::multiply_scale(std::vector<double> &multiply,
int pos) {
if (scale.size() != N-pos) {
std::cerr << "ERROR: Size of specified scale values does not match"
<< std::endl;
return(-1);
}
std::cerr << "Calibration constants changed! "
<< "OLD: " << this->scale[0];
for (int i=pos; i<std::min(N,(int)multiply.size()); i++){
this->scale[i] *= multiply[i-pos];
}
std::cerr << "NEW: " << this->scale[0] << std::endl;
}
/****************************************************************************
* *
* Calibration constants for the ADC *
* *
***************************************************************************/
int Obs_Calibration_Vector::get_adc_calibrate(std::string config,
std::string &offset, std::string &scale) {
std::string &offset, std::string &scale, std::string &mode) {
double temperature;
int ret=Obs_Calibration_Vector::get_adc_calibrate(config,offset,scale,mode,
temperature);
return(ret);
}
int Obs_Calibration_Vector::get_adc_calibrate(std::string config,
std::string &offset, std::string &scale, std::string &mode,
double &temperature) {
std::unordered_map<std::string, struct adc_cal>::iterator it;
struct adc_cal cal;
......@@ -113,9 +158,11 @@ int Obs_Calibration_Vector::get_adc_calibrate(std::string config,
cal = it->second;
scale = cal.scale;
offset = cal.offset;
mode = cal.mode;
} else {
scale = "";
offset = "";
mode = "";
return (-1);
}
......
......@@ -198,6 +198,9 @@ int driver_obs_obsdaq::get(data_obs_vector *data) {
// Parse data from answer
if (parse_data_ascii(data, buf) >= 0) {
// Calibrate the measurement/ASCII
driver_obs::cal->calibrate(data);
// Set the time
data->set_time(&recv_time);
......@@ -410,19 +413,15 @@ int driver_obs_obsdaq::stop() {
int driver_obs_obsdaq::manual_calibrate(int repeat, double freq) {
double tmp;
set_freq(freq);
calibrate(repeat,"MANUAL",tmp);
calibrate(repeat,"MANUAL");
}
int driver_obs_obsdaq::auto_calibrate(int repeat, double freq) {
double tmp;
set_freq(freq);
calibrate(repeat,"AUTO",tmp);
calibrate(repeat,"AUTO");
}
......@@ -438,13 +437,14 @@ int driver_obs_obsdaq::auto_calibrate(int repeat, double freq) {
* 1: Manual calibration
*
***************************************************************************/
int driver_obs_obsdaq::calibrate(int repeat, std::string mode,
double &fullscale) {
int driver_obs_obsdaq::calibrate(int repeat, std::string mode) {
int cal_done, cal_load;
std::string adc_scale, adc_offset, str_recv;
std::string adc_scale, adc_offset, adc_mode,str_recv;
double adc_temp;
char cmd[20]="";
std::string config;
std::vector<double> fullscale(3,0);
// Iterate over all three channels
for (int i = 0; i < 3; i++) {
......@@ -464,12 +464,13 @@ int driver_obs_obsdaq::calibrate(int repeat, std::string mode,
// Check if calibration for the given config
// was pre-determined
if (driver_obs::cal->get_adc_calibrate(config, adc_offset, adc_scale)
< 0) {
if (driver_obs::cal->get_adc_calibrate
(config, adc_offset, adc_scale, adc_mode, adc_temp) < 0) {
std::cerr << "CALIBRATION: " << mode << std::endl;
calibrate_channel(i, repeat, mode, config);
cal_done = 1;
adc_mode = mode;
} else {
......@@ -484,9 +485,12 @@ int driver_obs_obsdaq::calibrate(int repeat, std::string mode,
if (rsp == "y") {
calibrate_channel(i, repeat, mode, config);
cal_done = 1;
adc_mode = mode;
} else {
cal_load = 1;
}
} else {
cal_load = 1;
}
if (cal_load) {
......@@ -495,16 +499,20 @@ int driver_obs_obsdaq::calibrate(int repeat, std::string mode,
set_calibration(i, adc_offset, adc_scale);
std::cerr << "============ GOT: " << adc_offset << " "
<< adc_scale << std::endl;
// Set the fullscale value
}
}
if (adc_mode.compare(0,4,"MANU")==0) {
fullscale[i]=40.0;
} else {
fullscale[i]=42.5;
}
}
//TODO cal_done must be reset on every loop iteration for the channels.
// Else, we will never hit the PRE_DETERMIEND sector.
// Therefore, we need to check differently here if calibration should
// be written.
// Save calibration constants
if (cal_done) {
driver_obs::cal->save_adc_calibrate();
......@@ -512,8 +520,22 @@ int driver_obs_obsdaq::calibrate(int repeat, std::string mode,
<< cal->get_adc_calibrate() << std::endl;
}
//TODO REMOVE; and make separate fullscale for each channel
fullscale=42.5;
/////////////////////////////////////////////////////////////////////////
//
// Set the scaling parameter (Manual 12.5.1).
//
/////////////////////////////////////////////////////////////////////////
// Set the conversion parameters
//FULLSCALE=42.5; // Self-Gain calibration
//FULLSCALE=40.0; // System-Gain calibration
//GAIN=4.0; // +/- 10V range
//GAIN=8.0; // +/- 5V range
for (int i=0; i<fullscale.size();i++){
fullscale[i] = fullscale[i] / 4.0 / (double) 0x800000L;
}
driver_obs::cal->multiply_scale(fullscale);
return (0);
}
......@@ -1117,7 +1139,7 @@ int driver_obs_obsdaq::parse_data_ascii(data_obs_vector *data, char *buf) {
tmp[6] = 0; // String stop character
pos += 6;
n32 = strtol(tmp, NULL, 16);
n[i++] = ((long int) (n32 ^ num) - (long int) num) * M;
n[i++] = ((long int) (n32 ^ num) - (long int) num);
}
// Skip t:
......@@ -1289,21 +1311,21 @@ int driver_obs_obsdaq::parse_data_bin(data_obs_vector *data, char *buf) {
n32 = (((buf[2] & 0x7F) + ((buf[0] & 0x20) << 2)) << 16)
+ (((buf[3] & 0x7F) + ((buf[0] & 0x10) << 3)) << 8)
+ (((buf[4] & 0x7F) + ((buf[0] & 0x08) << 4)));
n[0] = ((long int) (n32 ^ num) - (long int) num) * M;
n[0] = ((long int) (n32 ^ num) - (long int) num);
//fprintf(stderr,"XYZ: %u %u %f\n",buf[2]&127,n32,n[0]);
// Channel 2
n32 = (((buf[5] & 127) + ((buf[0] & 4) << 5)) << 16)
+ (((buf[6] & 127) + ((buf[0] & 2) << 6)) << 8)
+ (((buf[7] & 127) + ((buf[0] & 1) << 7)));
n[1] = ((long int) (n32 ^ num) - (long int) num) * M;
n[1] = ((long int) (n32 ^ num) - (long int) num);
//fprintf(stderr,"XYZ: %u %f\n",n32,n[1]);
// Channel 3
n32 = (((buf[8] & 127) + ((buf[1] & 32) << 2)) << 16)
+ (((buf[9] & 127) + ((buf[1] & 16) << 3)) << 8)
+ (((buf[10] & 127) + ((buf[1] & 8) << 4)));
n[2] = ((long int) (n32 ^ num) - (long int) num) * M;
n[2] = ((long int) (n32 ^ num) - (long int) num);
//fprintf(stderr,"XYZ: %u %f\n",n32,n[2]);
//
......@@ -1483,7 +1505,7 @@ int driver_obs_obsdaq::init_run(double freq) {
// Index of the selected frequency
int freq_sel;
// Fullscale value (see manual 12.5.1)
double fullscale;
double fullscale[3];
// ADC calibration
std::string config;
......@@ -1492,25 +1514,7 @@ int driver_obs_obsdaq::init_run(double freq) {
set_freq(freq);
// Calibrate.
calibrate(5, "AUTO", fullscale);
/////////////////////////////////////////////////////////////////////////
//
// Set the scaling parameter (Manual 12.5.1).
//
/////////////////////////////////////////////////////////////////////////
//TODO Automatically set the calibration parameters
// Set the conversion parameters
//FULLSCALE=42.5; // Self-Gain calibration
//FULLSCALE=40.0; // System-Gain calibration
//GAIN=4.0; // +/- 10V range
//GAIN=8.0; // +/- 5V range
M = 42.5 / 4.0 / (double) 0x800000L;
//fprintf(stderr,"M: %f\n",M);
return (0);
calibrate(5, "AUTO");
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment