Newer
Older
// ============================================================================
//
// = CONTEXT
// TANGO Project - SCPI KeithleyElectrometer Support Library
//
// = FILENAME
// Keithley_6514.cpp
//
// = AUTHOR
// X. Elattaoui
//
// ============================================================================
// ============================================================================
// DEPENDENCIES
// ============================================================================
#include <iostream>
#include <sstream>
#include <string>
#include "Keithley_6514.h"
#include "KeithleySCPIProtocol.h"
/*
* Valid Range values for a K_6514
*/
static const std::string K6514_AMP_rangeStr[] = {"2E-11","2E-10","2E-9","2E-8","2E-7","2E-6","2E-5","2E-4","2E-3","2E-2"};
static const std::string K6514_VOLT_rangeStr[]= {"2","20","200"};
static const std::string K6514_OHM_rangeStr[] = {"2E3","2E4","2E5","2E6","2E7","2E8","2E9","2E10","2E11"};
static const std::string K6514_COU_rangeStr[] = {"2E-8","2E-7","2E-6","2E-5"};
static const short K6514_AMP_rangeLimit = 10;
static const short K6514_VOLT_rangeLimit= 3;
static const short K6514_OHM_rangeLimit = 9;
static const short K6514_COU_rangeLimit = 4;

ELATTAOUI
committed
static const unsigned short MAX_SAVED_CONFIG = 2;
/*
* Trigger Mode limit (millisec)
*/
static const int K6514_conversionRate = 175;
// ============================================================================
// Keithley_6514::Keithley_6514
// ============================================================================
Keithley_6514::Keithley_6514 (std::string& comLink_device_name)
: AbstractElectrometerClass(comLink_device_name),
_kmode("")
std::cout << "Keithley_6514::Keithley_6514 ->" << std::endl;
}
// ============================================================================
// Keithley_6514::~Keithley_6514
// ============================================================================
Keithley_6514::~Keithley_6514 (void)
{
std::cout << "Keithley_6514::~Keithley_6514 <-" << std::endl;
std::cout << "Keithley_6514::~Keithley_6514 ->" << std::endl;
}
// ============================================================================
// Keithley_6514::init_protocol
// ============================================================================
bool Keithley_6514::init_protocol (void)
{
std::string description("");
bool success = false;
try
{
//- build the keithley Electrometer protocol obj
_electrometerProtocol = new KeithleySCPIProtocol(_device_proxy_name);
if (_electrometerProtocol)
{
//- this model supports different mode (OhmMeter, VoltMeter and so on )
KeithleySCPIProtocol* _kscpi = dynamic_cast<KeithleySCPIProtocol*>(_electrometerProtocol);
if(_kscpi)
_kscpi->set_isDiffSuportedMode(true);
success = _electrometerProtocol->build_communicationLink();
}
}
catch(Tango::DevFailed& df)
{
description = "FAILED to create proxy on : " + _device_proxy_name;
Tango::Except::re_throw_exception (df,
(const char*)"COMMUNICATION_ERROR",
description.c_str(),
(const char*)"Keithley_6514::init_protocol");
}
catch(...)
{
description = "FAILED to create proxy on : " + _device_proxy_name + ". Caught [...].";
Tango::Except::throw_exception (
(const char*)"COMMUNICATION_ERROR",
description.c_str(),
(const char*)"Keithley_6514::init_protocol");
}
return success;
}
// ============================================================================
// Keithley_6514::range_up
// ============================================================================
{
std::stringstream cmd_to_send;
//- update range value from hardware
_range += 1;
//- check range validity
if(_kmode.find("CURR") != std::string::npos)
{
if(_range > K6514_AMP_rangeLimit)
{
_range = K6514_AMP_rangeLimit;
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range up limit reached.",
"Keithley_6514::range_up( ).");
}
_rangeStr = K6514_AMP_rangeStr[_range];
}
else
if (_kmode.find("VOLT") != std::string::npos)
{
if(_range > K6514_VOLT_rangeLimit)
{
_range = K6514_VOLT_rangeLimit;
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range up limit reached.",
"Keithley_6514::range_up( ).");
}
_rangeStr = K6514_VOLT_rangeStr[_range];
}
if (_kmode.find("RES") != std::string::npos)
{
if(_range > K6514_OHM_rangeLimit)
{
_range = K6514_OHM_rangeLimit;
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range up limit reached.",
"Keithley_6514::range_up( ).");
}
_rangeStr = K6514_OHM_rangeStr[_range];
}
else if (_kmode.find("CHAR") != std::string::npos)
{
if(_range > K6514_COU_rangeLimit)
{
_range = K6514_COU_rangeLimit;
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range up limit reached.",
"Keithley_6514::range_up( ).");
}
_rangeStr = K6514_COU_rangeStr[_range];
}
else
throw electrometer::ElectrometerException("UNKNOWN_MODE",
"Unable to find the electrometer mode used.",
"Keithley_6514::range_up( ).");
//- build and send the command
cmd_to_send << _rangeStr << std::endl;
_electrometerProtocol->set_range(cmd_to_send.str());
}
// ============================================================================
// Keithley_6514::range_down
// ============================================================================
{
std::stringstream cmd_to_send;
//- update range value from hardware
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range down limit reached.",
"Keithley_6514::range_down( ).");
}
//- check range validity
if(_kmode.find("CURR") != std::string::npos)
cmd_to_send << K6514_AMP_rangeStr[_range] << std::endl;
else if (_kmode.find("VOLT") != std::string::npos)
cmd_to_send << K6514_VOLT_rangeStr[_range] << std::endl;
else if (_kmode.find("RES") != std::string::npos)
cmd_to_send << K6514_OHM_rangeStr[_range] << std::endl;
else if (_kmode.find("CHAR") != std::string::npos)
cmd_to_send << K6514_COU_rangeStr[_range] << std::endl;
else
throw electrometer::ElectrometerException("UNKNOWN_MODE",
"Unable to find the electrometer mode used.",
"Keithley_6514::range_down( ).");
//- build and send the command
_electrometerProtocol->set_range(cmd_to_send.str());
}
// ============================================================================
// Keithley_6514::get_integratedValue
// ============================================================================
std::vector<double> Keithley_6514::get_integratedValue (void)
// ============================================================================
// Keithley_6514::get_fetchValue
// ============================================================================
std::vector<double> Keithley_6514::get_fetchValue (void)
// ============================================================================
// ============================================================================
{
_electrometerProtocol->setAmperMeterMode( );
}
// ============================================================================
// Keithley_6514::setVoltMeterMode
// ============================================================================
{
_electrometerProtocol->setVoltMeterMode( );
}
// ============================================================================
// Keithley_6514::setOhmMeterMode
// ============================================================================
{
_electrometerProtocol->setOhmMeterMode( );
}
// ============================================================================
// Keithley_6514::setCoulombMeterMode
// ============================================================================
{
_electrometerProtocol->setCoulombMeterMode( );
}
// ============================================================================
// ============================================================================
//void Keithley_6514::update_range (void)
std::string Keithley_6514::get_ElectroMeterRange (void)
{
std::string range_str("");
double rangeValueReturned = 0;
double rangeValueCalculated = 0;
double delta = 0;
/**
* NOTE : SCPI models return a range value +/- 5%
*/
_kmode = AbstractElectrometerClass::get_ElectroMeterMode();
//- get range from hardware
range_str = _electrometerProtocol->get_range( );
//- convert range in decimal value
rangeValueReturned = XString<double>::convertFromString(range_str);
//- find and return the index
short idx = 0;
short idx_limit = 0;
else if ( _kmode.find("VOLT") != std::string::npos )
else if ( _kmode.find("CHAR") != std::string::npos )
throw electrometer::ElectrometerException("UNKNOWN_MODE",
{
rangeValueCalculated = XString<double>::convertFromString(K6514_AMP_rangeStr[idx]);
delta = rangeValueCalculated * 5 / 100;
if( (rangeValueCalculated + delta) >= rangeValueReturned && (rangeValueCalculated - delta) <= rangeValueReturned)
break;
}
else if ( _kmode.find("VOLT") != std::string::npos )
{
rangeValueCalculated = XString<double>::convertFromString(K6514_VOLT_rangeStr[idx]);
delta = rangeValueCalculated * 5 / 100;
if( (rangeValueCalculated + delta) >= rangeValueReturned && (rangeValueCalculated - delta) <= rangeValueReturned)
break;
}
{
rangeValueCalculated = XString<double>::convertFromString(K6514_OHM_rangeStr[idx]);
delta = rangeValueCalculated * 5 / 100;
if( (rangeValueCalculated + delta) >= rangeValueReturned && (rangeValueCalculated - delta) <= rangeValueReturned)
break;
}
else if ( _kmode.find("CHAR") != std::string::npos )
{
rangeValueCalculated = XString<double>::convertFromString(K6514_COU_rangeStr[idx]);
delta = rangeValueCalculated * 5 / 100;
if( (rangeValueCalculated + delta) >= rangeValueReturned && (rangeValueCalculated - delta) <= rangeValueReturned)
break;
}
}
//- throw if index not found
throw electrometer::ElectrometerException("INTERNAL_ERROR",
//- update the range with the index found
this->_range = idx;
// ============================================================================
// Keithley_6514::set_knplc
// ============================================================================
{
std::stringstream cmd_to_send;
if(numPLC < 0.01 || numPLC > 10.0)
{
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Invalid number of PLC.\n Please enter a value in the range 0.01 to 10.0.",
"Keithley_6514::set_knplc( ).");
}
//- just for internal use
_numPLC = numPLC;
cmd_to_send << numPLC << std::endl;
//- default conversion rate
_electrometerProtocol->set_knplc(cmd_to_send.str());
// ============================================================================
// Keithley_6514::set_triggercount
// ============================================================================
void Keithley_6514::set_triggercount (short trigCounts)
{
std::stringstream cmd_to_send;
if(trigCounts == 0 || trigCounts > 2500)
{
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Invalid trigger count.\n Please enter a value in the range 1 to 2500 or set -1 for INFinite.",
"Keithley_6514::set_triggercount( ).");
}
if(trigCounts < 0)
cmd_to_send << "INF" << std::endl;
else
cmd_to_send << trigCounts << std::endl;
//- just for internal use
_trigCounts = trigCounts;
//- default conversion rate
_electrometerProtocol->set_triggercount(cmd_to_send.str());
// ============================================================================
// Keithley_6514::set_buffer_size
// ============================================================================
{
std::stringstream cmd_to_send;
if(size < 1 || size > 2500)
{
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Invalid buffer size. \nPlease enter a value in the range 1 to 2500.",
"Keithley_6514::set_buffer_size( ).");
}
//- just for internal use
_size = size;
cmd_to_send << size << std::endl;
//- default conversion rate
_electrometerProtocol->set_buffer_size(cmd_to_send.str());
// ============================================================================
// Keithley_6514::set_integrationTime
// ============================================================================
void Keithley_6514::set_integrationTime (double seconds)
{
//- set the number of Power Line Cycle(s) -> Fast integration
_numPLC = 0.05;
//- set the number of trigger(s) ~ buffer size
_trigCounts = (short)ceil(seconds / _numPLC);
if(_trigCounts > 2500)
_trigCounts = 2500;
}
// ============================================================================
// Keithley_6514::init_keithley : command to perform an integration cycle
// ============================================================================
{
//- get data only (no timestamp info ... wanted!)
_electrometerProtocol->read_data_with_no_timestamp();
//- Set integration rate in line cycles
this->set_knplc(_numPLC);
//- Set trigger model to take to N readings
this->set_triggercount(_trigCounts);
//- Set buffer size
this->set_buffer_size(_size);
//- clear previous data
_electrometerProtocol->clear_buffer();
//- Store raw input
_electrometerProtocol->store_raw_input();
//- Start storing readings
_electrometerProtocol->start_storing();
//- Trigger readings
_electrometerProtocol->init_keithley();
}

ELATTAOUI
committed
// ============================================================================
// Keithley_6514::save_configuration
// ============================================================================
void Keithley_6514::save_configuration (unsigned short memoryIdx)

ELATTAOUI
committed
{
if( memoryIdx > MAX_SAVED_CONFIG )
{
throw electrometer::ElectrometerException("OUT_OF_RANGE",

ELATTAOUI
committed
"Index of saved configuration must be in the range [0-2].",
"Keithley_6514::save_configuration( ).");
}
_electrometerProtocol->save_configuration(memoryIdx);
}
// ============================================================================
// Keithley_6514::restore_configuration
// ============================================================================
void Keithley_6514::restore_configuration (unsigned short memoryIdx)

ELATTAOUI
committed
{
if( memoryIdx > MAX_SAVED_CONFIG )
{
throw electrometer::ElectrometerException("OUT_OF_RANGE",