Commit 7af972ae authored by Achim Morschhauser's avatar Achim Morschhauser
Browse files

ADC calibrate #7 save cal working

parent 9a7f6786
...@@ -31,8 +31,14 @@ private: ...@@ -31,8 +31,14 @@ private:
/** ADC calibration constant */ /** ADC calibration constant */
struct adc_cal { struct adc_cal {
std::string offset;
std::string scale; std::string scale;
std::string offset;
bool operator==(const adc_cal& a) const {
return (scale == a.scale && offset == a.offset);
}
}; };
/** Map containing the ADC calibration key-value pairs */ /** Map containing the ADC calibration key-value pairs */
...@@ -99,6 +105,8 @@ public: ...@@ -99,6 +105,8 @@ public:
/** Set the internal ADC calibration file */ /** Set the internal ADC calibration file */
int set_adc_calibrate(std::string filename); int set_adc_calibrate(std::string filename);
/** Get the internal ADC calibration file */
std::string get_adc_calibrate();
}; };
......
...@@ -163,6 +163,9 @@ int init(); ...@@ -163,6 +163,9 @@ int init();
/** Prepare continuous data acquisition **/ /** Prepare continuous data acquisition **/
int init_run(double freq); int init_run(double freq);
/** Automatically calibrate the ObsDAQ with given config*/
int auto_calibrate(int channel, int repeat, std::string config);
}; };
#endif /* _DRIVER_OBS_OBSDAQ_H */ #endif /* _DRIVER_OBS_OBSDAQ_H */
// C++ headers // C++ headers
#include <string> // String #include <string> // String
#include <iostream> // String streams #include <iostream> // I/O
#include <sstream> // String streams
#include <fstream> // File operations #include <fstream> // File operations
#include <unordered_map> #include <unordered_map>
...@@ -164,12 +165,12 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config, ...@@ -164,12 +165,12 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
cal.scale = scale; cal.scale = scale;
// Check if already exists // Check if already exists
if (map_ADC.count(config)>0) { if (map_ADC.count(config)>0) {
map_ADC[config]=cal; std::cerr << "Calibration for " << config << " overwritten."
} else { << std::endl;
std::cerr << "Calibration for " << config << " overwritten.";
} }
map_ADC[config]=cal;
return(0); return(0);
...@@ -188,14 +189,21 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config, ...@@ -188,14 +189,21 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
* file. Comment out duplicates instead of overwriting. * file. Comment out duplicates instead of overwriting.
*/ */
std::ifstream file_buf(filename); std::ifstream file_in(filename);
std::ofstream file_out; std::ofstream file_out;
std::string line, config, comment; std::string line, config, comment;
std::stringstream buf_in;
size_t pos_c; size_t pos_c;
struct adc_cal cal; struct adc_cal cal, cal_buf;
// Copy the file to stringstream
if (file_in) {
buf_in << file_in.rdbuf();
file_in.close();
}
// Copy the hash map // Copy the hash map
// The copy will be used to track what has been written to file // The copy will be used to track what has been written to file
std::unordered_map<std::string, struct adc_cal> map_ADC_cpy(map_ADC); std::unordered_map<std::string, struct adc_cal> map_ADC_cpy(map_ADC);
...@@ -204,22 +212,30 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config, ...@@ -204,22 +212,30 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
file_out.open(filename,std::ios::out | std::ios::trunc); file_out.open(filename,std::ios::out | std::ios::trunc);
// Read from buffered file // Read from buffered file
while ( getline (file_buf,line) ) { while ( getline (buf_in,line) ) {
// Parse from line // Parse from line
if (parse_adc_calibration(line,config,cal,comment) < 0){ // Comment line
if (parse_adc_calibration(line,config,cal_buf,comment) < 0){
file_out << line << std::endl; file_out << line << std::endl;
} else { } else {
// Configuration exists and is overwritten // Configuration exists
if (map_ADC_cpy.count(config)>0) { if (map_ADC_cpy.count(config)>0) {
file_out << "#" << line << std::endl;
cal=map_ADC_cpy[config]; cal=map_ADC_cpy[config];
file_out << config << "," << cal.offset << "," << map_ADC_cpy.erase(config);
// Existing config is the same
if (cal==cal_buf){
file_out << line << std::endl;
// Existing config is different
} else {
file_out << "#" << line << std::endl;
file_out << config << "," << cal.offset << "," <<
cal.scale << ";" << comment << std::endl; cal.scale << ";" << comment << std::endl;
}
// Configuration doesn't exist // Configuration doesn't exist
} else { } else {
...@@ -230,6 +246,13 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config, ...@@ -230,6 +246,13 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
} }
// Write all remaining configurations
for (auto& i : map_ADC_cpy){
file_out << i.first << "," << i.second.scale << ","
<< i.second.offset << ";" << std::endl;
}
file_out.close(); file_out.close();
...@@ -318,10 +341,10 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config, ...@@ -318,10 +341,10 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
// Find calibration string // Find calibration string
line=line.substr(pos_c+1); line=line.substr(pos_c+1);
pos_c=line.find(','); pos_c=line.find(',');
cal.offset = line.substr(0,pos_c); cal.scale = line.substr(0,pos_c);
line=line.substr(pos_c+1); line=line.substr(pos_c+1);
pos_c=line.find(';'); pos_c=line.find(';');
cal.scale = line.substr(0,pos_c); cal.offset = line.substr(0,pos_c);
return(0); return(0);
} }
...@@ -342,4 +365,10 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config, ...@@ -342,4 +365,10 @@ int Obs_Calibration_Vector::add_adc_calibrate(std::string config,
return(0); return(0);
}
std::string Obs_Calibration_Vector::get_adc_calibrate() {
return(file_ADC);
} }
\ No newline at end of file
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <buffer_obs.hpp> // Buffer for data #include <buffer_obs.hpp> // Buffer for data
#include <data_obs_vector.hpp> // Vector data structure #include <data_obs_vector.hpp> // Vector data structure
#include <driver_obs_obsdaq.hpp> // Generic observatory driver #include <driver_obs_obsdaq.hpp> // Generic observatory driver
#include <Obs_Calibration_Vector.hpp> // Calibration routines
/******************************************************************************* /*******************************************************************************
******************************************************************************* *******************************************************************************
...@@ -414,7 +415,8 @@ int driver_obs_obsdaq::stop() { ...@@ -414,7 +415,8 @@ int driver_obs_obsdaq::stop() {
* Individual calibration steps are averaged. * Individual calibration steps are averaged.
* *
***************************************************************************/ ***************************************************************************/
int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat,
std::string config){
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
...@@ -428,6 +430,8 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){ ...@@ -428,6 +430,8 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){
// The calibration constants // The calibration constants
double offset=0, scale=0; double offset=0, scale=0;
// Calibration constants as string
std::string offset_str, scale_str;
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
...@@ -465,31 +469,31 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){ ...@@ -465,31 +469,31 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){
while (checked_send(cmd,"R0",2,5)<0){ while (checked_send(cmd,"R0",2,5)<0){
} }
// Read the offset value // Read the full-scale value
sprintf(cmd,"$%1dRO",channel); sprintf(cmd,"$%1dRF",channel);
send(cmd); send(cmd);
//TODO Repeat loop instead of just omitting //TODO Repeat loop instead of just omitting
if (receive(recv,sizeof(recv),5)==0) { if (receive(recv,sizeof(recv),5)==0) {
// Parse the offset value and add to average // Parse the full-scale value and add to average
n32 = (uint32_t) strtoul(&recv[3], NULL, 16); n32 = (uint32_t) strtoul(&recv[3], NULL, 16);
num=0x800000L; num=0x800000L;
offset += (double) (n32 ^ num) - (double) num; scale += (double) (n32 ^ num) - (double) num;
} }
// Necessary to avoid time outs // Necessary to avoid timeouts
usleep(1e6); usleep(1e6);
// Read the full-scale value
sprintf(cmd,"$%1dRF",channel); // Read the offset value
sprintf(cmd,"$%1dRO",channel);
send(cmd); send(cmd);
//TODO Repeat loop instead of just omitting //TODO Repeat loop instead of just omitting
if (receive(recv,sizeof(recv),5)==0) { if (receive(recv,sizeof(recv),5)==0) {
// Parse the full-scale value and add to average // Parse the offset value and add to average
n32 = (uint32_t) strtoul(&recv[3], NULL, 16); n32 = (uint32_t) strtoul(&recv[3], NULL, 16);
num=0x800000L; num=0x800000L;
scale += (double) (n32 ^ num) - (double) num; offset += (double) (n32 ^ num) - (double) num;
} }
} }
...@@ -499,22 +503,33 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){ ...@@ -499,22 +503,33 @@ int driver_obs_obsdaq::auto_calibrate(int channel, int repeat){
// OBSDAQ. // OBSDAQ.
// //
// Offset // Full-scale
n32 = ((int32_t) (scale/repeat) + (int32_t) 0x800000L) n32 = ((int32_t) (scale/repeat) + (int32_t) 0x800000L)
^ (int32_t) 0x800000L ; ^ (int32_t) 0x800000L ;
sprintf(cmd,"$%1dWF%06X",channel,n32); sprintf(cmd,"$%1dWF%06X",channel,n32);
send(cmd); send(cmd);
scale_str=offset_str.substr(4,6);
waitanswer(1);
std::cerr << "Set offset: " << scale/repeat << " " << cmd << std::endl; std::cerr << "Set scale: " << scale/repeat << " " << cmd << std::endl;
// Full-scale // Offset
n32 = ((int32_t) (offset/repeat) + (int32_t) 0x800000L) n32 = ((int32_t) (offset/repeat) + (int32_t) 0x800000L)
^ (int32_t) 0x800000L; ^ (int32_t) 0x800000L;
sprintf(cmd,"$%1dWO%06X",channel,n32); sprintf(cmd,"$%1dWO%06X",channel,n32);
send(cmd); send(cmd);
offset_str=std::string(cmd).substr(4,6);
waitanswer(1);
std::cerr << "Set scale: " << scale/repeat << " " << cmd << std::endl; std::cerr << "Set offset: " << offset/repeat << " " << cmd << std::endl;
/////////////////////////////////////////////////////////////////////////
//
// Store the new calibration values
//
/////////////////////////////////////////////////////////////////////////
cal->add_adc_calibrate(config,offset_str,scale_str);
return(0); return(0);
} }
...@@ -1103,6 +1118,7 @@ int driver_obs_obsdaq::init_run(double freq){ ...@@ -1103,6 +1118,7 @@ int driver_obs_obsdaq::init_run(double freq){
// Iterate over all three channels // Iterate over all three channels
for (int i=0; i<3; i++){ for (int i=0; i<3; i++){
// Get current 24-bit configuration (Manual 12.4.9) // Get current 24-bit configuration (Manual 12.4.9)
flush();
sprintf(cmd,"$%1dRS",i); sprintf(cmd,"$%1dRS",i);
send(cmd); send(cmd);
receive(recv,sizeof(recv),5); receive(recv,sizeof(recv),5);
...@@ -1119,7 +1135,7 @@ int driver_obs_obsdaq::init_run(double freq){ ...@@ -1119,7 +1135,7 @@ int driver_obs_obsdaq::init_run(double freq){
if (driver_obs::cal->get_adc_calibrate if (driver_obs::cal->get_adc_calibrate
(config, adc_offset, adc_scale)<0){ (config, adc_offset, adc_scale)<0){
// Automatic Calibration // Automatic Calibration
auto_calibrate(i,1); auto_calibrate(i,1,config);
auto_cal=1; auto_cal=1;
} else { } else {
// Set the pre-determined calibration constant // Set the pre-determined calibration constant
...@@ -1134,7 +1150,11 @@ int driver_obs_obsdaq::init_run(double freq){ ...@@ -1134,7 +1150,11 @@ int driver_obs_obsdaq::init_run(double freq){
} }
// Save calibration constants // Save calibration constants
if (auto_cal) driver_obs::cal->save_adc_calibrate(); if (auto_cal) {
driver_obs::cal->save_adc_calibrate();
std::cerr << "New calibration constants written to "
<< cal->get_adc_calibrate() << std::endl;
}
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
......
Markdown is supported
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