Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Keithley_6512.cpp 15.69 KiB
// ============================================================================
//
// = CONTEXT
// TANGO Project - KeithleyElectrometer Support Library
//
// = FILENAME
// Keithley_6512.cpp
//
// = AUTHOR
// X. Elattaoui
//
// ============================================================================
static long KEITHLEY_MODEL = 6512;
// ============================================================================
// DEPENDENCIES
// ============================================================================
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <Xstring.h>
#include "Keithley_6512.h"
#include "KeithleyDDCProtocol.h"
/*
* Valid Range values for a K_6512
*/
static const std::string K6512_AmpRangeValue[] = {"AUTO ON","2E-12","2E-11","2E-10","2E-9","2E-8","2E-7","2E-6","2E-5","2E-4","2E-3","2E-2", "AUTO OFF"};
static const std::string K6512_VoltRangeValue[]= {"AUTO ON","2E-1","2","20","200","200","200","200","200","200","200","200", "AUTO OFF"};
static const std::string K6512_OhmRangeValue[] = {"AUTO ON","2E3","2E4","2E5","2E6","2E7","2E8","2E9","2E10","2E11","2E11","2E11", "AUTO OFF"};
static const std::string K6512_CouRangeValue[] = {"AUTO ON","2E-10","2E-9","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10", "AUTO OFF"};
static const std::string K6512_XfdbRangeValue[]= {"AUTO ON","2E-1","2","20","20","20","20","20","20","20","20","20", "AUTO OFF"};
/*
* Range limit
*/
static short K6512_rangeLimit = 12;
/*
* Trigger Mode limit
*/
static short K6512_triggerModeLimit = 7;
// ============================================================================
// Keithley_6512::Keithley_6512
// ============================================================================
Keithley_6512::Keithley_6512 (std::string& comLink_device_name)
: AbstractElectrometerClass(comLink_device_name)
{
std::cout << "Keithley_6512::Keithley_6512 <-" << std::endl;
//- build the keithley Electrometer obj
_electrometerProtocol = new KeithleyDDCProtocol (_device_proxy_name);
std::cout << "Keithley_6512::Keithley_6512 ->" << std::endl;
}
// ============================================================================
// Keithley_6512::~Keithley_6512
// ============================================================================
Keithley_6512::~Keithley_6512 (void)
{
std::cout << "Keithley_6512::~Keithley_6512 <-" << std::endl;
std::cout << "Keithley_6512::~Keithley_6512 ->" << std::endl;
}
// ============================================================================
// Keithley_6512::autoRange_off
// ============================================================================
void Keithley_6512::autoRange_off (void)
{
KeithleyDDCProtocol* _kddc = dynamic_cast<KeithleyDDCProtocol*>(_electrometerProtocol);
if(_kddc)
_kddc->autoRange_OFF_forK617_6512();
}
// ============================================================================
// Keithley_6512::range_up
// ============================================================================
void Keithley_6512::range_up (void)
{
std::stringstream cmd_to_send;
// force read of range on instrument to update _range variable
electrometer_status();
_range += 1;
if(_range > K6512_rangeLimit)
{
_range = K6512_rangeLimit;
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range up limit reached.",
"Keithley_6512::range_up( ).");
}
//- build and send the command
cmd_to_send << _range << std::endl;
_electrometerProtocol->set_range(cmd_to_send.str());
}
// ============================================================================
// Keithley_6512::range_down
// ============================================================================
void Keithley_6512::range_down (void)
{
std::stringstream cmd_to_send;
// force read of range on instrument to update _range variable
electrometer_status();
_range -= 1;
if(_range < 0)
{
_range =0;
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range down limit reached.",
"Keithley_6512::range_down( ).");
}
//- build and send the command
cmd_to_send << _range << std::endl;
_electrometerProtocol->set_range(cmd_to_send.str());
}
// ============================================================================
// Keithley_6512::get_ElectroMeterRange
// ============================================================================
std::string Keithley_6512::get_ElectroMeterRange (void)
{
// force read of range on instrument to update _range variable
electrometer_status();
return _rangeStr;
}
// ============================================================================
// Keithley_6512::set_buffer_size()
// ============================================================================
void Keithley_6512::set_buffer_size (short )
{
//std::string cmd_to_send("");
throw electrometer::ElectrometerException("COMMAND_NOT_SUPPORTED",
"The 6512 Keithley device buffer size cannot be set (it stores up to 100 points internally.)",
"Keithley_6512::set_triggerMode( ).");
}
// ============================================================================
// Keithley_6512::set_triggerMode
// ============================================================================
void Keithley_6512::set_triggerMode (short trigMod)
{
if(trigMod<0 || trigMod>K6512_triggerModeLimit)
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Trigger mode value invalid. Please enter a value in the range 0 - 7.",
"Keithley_6512::set_triggerMode( ).");
std::stringstream cmd_to_send;
//- just for internal use
_trigMod = trigMod;
cmd_to_send << "T" << trigMod << "X" << std::endl;
_electrometerProtocol->set_triggerMode(cmd_to_send.str());
}
// ============================================================================
// Keithley_6512::get_ElectroMeterMode
// ============================================================================
std::string Keithley_6512::get_ElectroMeterMode (void)
{
// force read of mode on instrument to update _mode variable
electrometer_status();
return _mode;
}
// ============================================================================
// Keithley_6512::setAmperMeterMode (617 & 6512 Keithley DDC models
// ============================================================================
void Keithley_6512::setAmperMeterMode (void)
{
_electrometerProtocol->setAmperMeterMode( );
}
// ============================================================================
// Keithley_6512::setVoltMeterMode (617 & 6512 Keithley DDC models
// ============================================================================
void Keithley_6512::setVoltMeterMode (void)
{
_electrometerProtocol->setVoltMeterMode( );
}
// ============================================================================
// Keithley_6512::setOhmMeterMode (617 & 6512 Keithley DDC models
// ============================================================================
void Keithley_6512::setOhmMeterMode (void)
{
_electrometerProtocol->setOhmMeterMode( );
}
// ============================================================================
// Keithley_6512::setCoulombMeterMode (617 & 6512 Keithley DDC models
// ============================================================================
void Keithley_6512::setCoulombMeterMode (void)
{
_electrometerProtocol->setCoulombMeterMode( );
}
// ============================================================================
// Keithley_6512::init_keithley : command to perform an integration cycle
// ============================================================================
void Keithley_6512::init_keithley (void)
{
//- set trigger mode
this->set_triggerMode(_trigMod);
//- default conversion rate
_electrometerProtocol->set_conversionRate( );
//- force readings with no prefix
_electrometerProtocol->disable_readingWithPrefix();
//- force readings from device buffer
_electrometerProtocol->enable_readingsFromBuffer_K617_6512();
//- enable SRQ on buffer full
_electrometerProtocol->enable_SRQBufferFull ();
}
// ============================================================================
// Keithley_6512::electrometer_status
// ============================================================================
std::string Keithley_6512::electrometer_status (void)
{
std::string kconfig("undefined configuration");
std::string argout("");
std::string tmp("");
try
{
kconfig = _electrometerProtocol->get_raw_status();
std::string modelNum = kconfig.substr(0,4);
if(modelNum.find("6512") == std::string::npos)
{
set_electroState(ALARM);
argout = "Invalid error status string received";
return argout;
}
//- IDDC Error : Set when an illegal device dependent command (IDDC) such as HlX is received ("H" is illegal).
tmp = kconfig.substr(4,1);
short iddc = XString<short>::convertFromString(tmp);
if(iddc)
{
argout += "IDDC error : illegal device dependent command received.\n";
}
//- IDDCO Error : Set when an illegal device-dependent command option (IDDCO) such as T9X is received ("9" is illegal).
tmp = kconfig.substr(5,1);
short iddco = XString<short>::convertFromString(tmp);
if(iddco)
{
argout += "IDDCO error : an illegal device-dependent command option received.\n";
}
//- Remote Error : Set when a programming command is received when REN is false.
tmp = kconfig.substr(6,1);
short remote = XString<short>::convertFromString(tmp);
if(remote)
{
argout += "REMOTE error : programming command is received when REN is false\n";
}
//- Trigger Overrun Error : Set when a trigger is received when the instrument is still processing a reading from a previous trigger.
tmp = kconfig.substr(8,1);
short trigg = XString<short>::convertFromString(tmp);
if(trigg)
{
argout += "Trigger error : Trigger received while instrument is still processing a reading from a previous trigger.\n";
}
//- Number Error : Set when an Out of range calibration or voltage source value is received.
tmp = kconfig.substr(9,1);
short numErr = XString<short>::convertFromString(tmp);
if(numErr)
{
argout += "Number error : Out of range calibration or voltage source value is received.\n";
}
if( argout.empty() )
argout = "No error.";
argout = "Keithley Type " + modelNum + " Error Status :\n" + argout;
}
catch(...)
{
set_electroState(ALARM);
throw electrometer::ElectrometerException("UNKNOWN_ERROR",
"Cannot extract device error status.",
"Keithley_6512::electrometer_status( ).");
}
set_electroState(ON);
return argout;
}
// ============================================================================
// Keithley_6512::get_configuration
// ============================================================================
std::string Keithley_6512::get_configuration (void)
{
std::string _kstatus("undefined status");
std::string argout("undefined status");
std::string tmp("");
//- read keithley status from HW
_kstatus = _electrometerProtocol->get_DDC_configuration();
//- build status
try
{
//- model number :
std::string modelNum = _kstatus.substr(0,4);
//- if not expected data (here model number)
if(modelNum.find("6512") == std::string::npos)
{
set_electroState(ALARM);
argout = "Invalid status string received";
return argout;
}
argout = "Keithley Type : " + modelNum + "\n";
//- Functions and associate range :
tmp = _kstatus.substr(4,1);
short func = XString<short>::convertFromString(tmp);
//- Range :
tmp = _kstatus.substr(5,2);
_range = XString<short>::convertFromString(tmp);
if(!func)
{
_mode = "Function : VOLTS";
argout += _mode + "\n";
_rangeStr = K6512_VoltRangeValue[_range];
}
else
if(func == 1)
{
_mode = "Function : AMPS";
argout += _mode + "\n";
_rangeStr = K6512_AmpRangeValue[_range];
argout += _rangeStr + "\n";
}
else
if(func == 2)
{
_mode = "Function : OHMS";
argout += _mode + "\n";
_rangeStr = K6512_OhmRangeValue[_range];
}
else
if(func == 3)
{
_mode = "Function : COULOMBS";
argout += _mode + "\n";
_rangeStr = K6512_CouRangeValue[_range];
}
else
if(func == 4)
{
_mode = "Function : XFDBK";
argout += _mode + "\n";
_rangeStr = K6512_XfdbRangeValue[_range];
}
//- Range :
argout += "RANGE : " + _rangeStr + "\n";
//- Zero check state
tmp = _kstatus.substr(7,1);
if(XString<short>::convertFromString(tmp))
argout += "Zero Check : ON\n";
else
argout += "Zero Check : OFF\n";
//- Zero correct state
tmp = _kstatus.substr(8,1);
if(XString<short>::convertFromString(tmp))
argout += "Zero Correct : ON\n";
else
argout += "Zero Correct : OFF\n";
//- Suppress
tmp = _kstatus.substr(9,1);
if(XString<short>::convertFromString(tmp))
argout += "Suppress : ON\n";
else
argout += "Suppress : OFF\n";
//- Trigger
tmp = _kstatus.substr(10,1);
short trigg = XString<short>::convertFromString(tmp);
if(!trigg)
argout += "Trigger : Continuous on Talk\n";
else
if(trigg == 1)
argout += "Trigger :One-Shot on Talk\n";
else
if(trigg == 2)
argout += "Trigger :Continuous on Get\n";
else
if(trigg == 3)
argout += "Trigger :One-Shot on Get\n";
else
if(trigg == 4)
argout += "Trigger :Continuous on \"X\"\n";
else
if(trigg == 5)
argout += "Trigger :One-Shot on \"X\"\n";
else
if(trigg == 6)
argout += "Trigger :Continuous on External\n";
else
if(trigg == 7)
argout += "Trigger :One-Shot on External\n";
//- Read Mode
tmp = _kstatus.substr(12,1);
short readingMode = XString<short>::convertFromString(tmp);
if(!readingMode)
argout += "Read Mode : Electrometer\n";
else
if(readingMode == 1)
argout += "Read Mode : Data Store\n";
else
if(readingMode == 2)
argout += "Read Mode : Maximum\n";
else
if(readingMode == 3)
argout += "Read Mode : Minimum\n";
else
if(readingMode == 4)
argout += "Read Mode :Voltage Source\n";
//- Data Store
tmp = _kstatus.substr(15,1);
short dstore = XString<short>::convertFromString(tmp);
if(!dstore)
argout += "Data Store : Conversion Rate\n";
else
if(dstore == 1)
argout += "Data Store : 1 RDG/Sec\n";
else
if(dstore == 2)
argout += "Data Store : 1 RDG/10Sec\n";
else
if(dstore == 3)
argout += "Data Store : 1 RDG/Min\n";
else
if(dstore == 4)
argout += "Data Store : 1 RDG/10Min\n";
else
if(dstore == 5)
argout += "Data Store : 1 RDG/1Hr\n";
else
if(dstore == 6)
argout += "Data Store : Trig Button\n";
else
if(dstore == 7)
argout += "Data Store : Disabled\n";
//- SRQ Mask
tmp = _kstatus.substr(16,2);
short srqInfo = XString<short>::convertFromString(tmp);
if(!srqInfo)
argout += "SRQ Data Mask : SRQ Disabled\n";
else
if(srqInfo == 1)
argout += "SRQ Data Mask : Reading Overflow\n";
else
if(srqInfo == 2)
argout += "SRQ Data Mask : Data Store Full\n";
else
if(srqInfo == 8)
argout += "SRQ Data Mask : Reading Done\n";
else
if(srqInfo == 16)
argout += "SRQ Data Mask : Ready\n";
else
if(srqInfo == 32)
argout += "SRQ Data Mask : Error\n";
//- EOI & Bus Hold Off
tmp = _kstatus.substr(18,1);
short ebhoff = XString<short>::convertFromString(tmp);
if(!ebhoff)
argout += "EOI & Bus Hold Off : EOI and Hold-Off\n";
else
if(ebhoff == 1)
argout += "EOI & Bus Hold Off : No EOI and Hold-Off\n";
else
if(ebhoff == 2)
argout += "EOI & Bus Hold Off : EOI and no Hold-Off\n";
else
if(ebhoff == 3)
argout += "EOI & Bus Hold Off : No EOI and no Hold-Off\n";
}
catch(std::out_of_range)
{
set_electroState(ALARM);
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Cannot extract device status [find or substr failed !].",
"Keithley_6512::get_configuration( ).");
}
set_electroState(ON);
return argout;
}