Skip to content
Snippets Groups Projects
Select Git revision
  • 0779db1d9c228f19825b501f0f037da07d5034a2
  • main default protected
  • develop
  • release_2_8_3
  • release_2_8_2
  • release_2_8_1
  • release_2_8_0
  • release_2_7_1
  • release_2_7_0
  • release_2_6_0
  • release_2_5_29
  • release_2_5_28
  • release_2_5_27
  • release_2_5_26
  • release_2_5_25
  • release_2_5_24
  • release_2_5_23
  • release_2_5_22
  • release_2_5_21
  • release_2_5_20
  • release_2_5_18
  • release_2_5_17
  • release_2_5_16
23 results

Keithley_6514.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    Keithley_6514.cpp 13.71 KiB
    // ============================================================================
    //
    // = CONTEXT
    //    TANGO Project - SCPI KeithleyElectrometer Support Library
    //
    // = FILENAME
    //    Keithley_6514.cpp
    //
    // = AUTHOR
    //    X. Elattaoui
    //
    // ============================================================================
    static long KEITHLEY_MODEL = 6514;
    
    // ============================================================================
    // DEPENDENCIES
    // ============================================================================
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <math.h>   //- for ceil
    #include <Xstring.h>
    #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"};
    /*
    * Max Index Range value for a K_6514
    */
    static const short K6514_AMP_rangeLimit = 9;
    static const short K6514_VOLT_rangeLimit= 2;
    static const short K6514_OHM_rangeLimit = 8;
    static const short K6514_COU_rangeLimit = 3;
    
    /*
    * 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;
    
    	//- build the keithley Electrometer obj
    	_electrometerProtocol = new KeithleySCPIProtocol(_device_proxy_name);
    
      _numPLC     = 0;
      _trigCounts = 0;
      _size       = 0;
    	//- this model supports different mode (OhmMeter, VoltMeter and so on )
    	KeithleySCPIProtocol* _kscpi = dynamic_cast<KeithleySCPIProtocol*>(_electrometerProtocol);
    	if(_kscpi)
    		_kscpi->set_isDiffSuportedMode(true);
    
    	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::range_up
    // ============================================================================
    void Keithley_6514::range_up (void) 
    {
    
    std::stringstream cmd_to_send;
    
    	//- update range value from hardware
    	update_range( );
    
    	_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];
    	}
    	else 
    	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
    // ============================================================================
    void Keithley_6514::range_down (void) 
    {
    
    std::stringstream cmd_to_send;
    
    	//- update range value from hardware
    	update_range( );
    
    	_range -= 1;
    
    	if(_range < 0)
    	{
    		_range = 0;
    
    		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) 
    {
      return 	_electrometerProtocol->get_integratedValue( );
    }  
    
    // ============================================================================
    // Keithley_6514::get_fetchValue
    // ============================================================================
    std::vector<double> Keithley_6514::get_fetchValue (void) 
    {
      return 	_electrometerProtocol->get_fetchValue( );
    }  
    
    // ============================================================================
    // Keithley_6514::setAmperMeterMode 
    // ============================================================================
    void Keithley_6514::setAmperMeterMode (void) 
    {
    
    	_electrometerProtocol->setAmperMeterMode( );
    
    
    }
    
    // ============================================================================
    // Keithley_6514::setVoltMeterMode
    // ============================================================================
    void Keithley_6514::setVoltMeterMode (void) 
    {
    
    	_electrometerProtocol->setVoltMeterMode( );
    
    }
    
    // ============================================================================
    // Keithley_6514::setOhmMeterMode
    // ============================================================================
    void Keithley_6514::setOhmMeterMode (void) 
    {
    
    	_electrometerProtocol->setOhmMeterMode( );
    
    }
    
    // ============================================================================
    // Keithley_6514::setCoulombMeterMode
    // ============================================================================
    void Keithley_6514::setCoulombMeterMode (void) 
    {
    
    	_electrometerProtocol->setCoulombMeterMode( );
    
    }
    
    // ============================================================================
    // Keithley_6514::update_range
    // ============================================================================
    void Keithley_6514::update_range (void) 
    {
    std::string range_str("");
    double rangeValueReturned	= 0;
    double rangeValueCalculated	= 0;
    double delta = 0;
    
    	/**
    	*	NOTE : SCPI models return a range value +/- 5%
    	*/
    
    	//- get device mode 
    	_kmode = 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;
    
    	if(_kmode.find("CURR") != std::string::npos)
    		idx_limit = K6514_AMP_rangeLimit;
    	else if (_kmode.find("VOLT") != std::string::npos)
    		idx_limit = K6514_VOLT_rangeLimit;
    	else if (_kmode.find("RES") != std::string::npos)
    		idx_limit = K6514_OHM_rangeLimit;
    	else if (_kmode.find("CHAR") != std::string::npos)
    		idx_limit = K6514_COU_rangeLimit;
    	else
    		throw electrometer::ElectrometerException("UNKNOWN_MODE", 
    												"Unable to find the electrometer mode used.",
    												"Keithley_6514::update_range( ).");
    
    	
    //- find the range index
    	for(idx=0; idx<idx_limit ; idx++)
    	{
    		if(_kmode.find("CURR") != std::string::npos)
    		{
    			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;
    		}
    		else if (_kmode.find("RES") != std::string::npos)
    		{
    			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
    	if(idx == idx_limit)
    		throw electrometer::ElectrometerException("INTERNAL_ERROR", 
    										"Failed to get range index.",
    										"Keithley_6514::update_range( ).");
    
    	//- update the range with the index found
    	this->_range = idx;
    }
    
    // ============================================================================
    // Keithley_6514::set_knplc
    // ============================================================================
    void Keithley_6514::set_knplc (float numPLC) 
    {
    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
    // ============================================================================
    void Keithley_6514::set_buffer_size (short 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
    // ============================================================================
    void Keithley_6514::init_keithley (void) 
    {
      //- 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();
    }