/*------------------------------------------------------------ * GPIBPixDcx.cxx * Version: 0.1.USBsystem * Created: 19 February 2009 * Author: Joern Grosse-Knetter * * Functional interface to the USB system for communication * with GPIB devices *------------------------------------------------------------*/ #include "PixDcs/GPIBPixDcs.h" #include "Config/Config.h" #include "Config/ConfGroup.h" #include "PixConfDBInterface/PixConfDBInterface.h" #include "PixGPIBDevice.h" #include "SleepWrapped.h" #include #include using namespace PixLib; GPIBPixDcsChan::GPIBPixDcsChan(PixDcs *parent, DBInquire *dbInquire) : PixDcsChan(parent, dbInquire){ configInit(); m_conf->read(dbInquire); // get last part of decorated name which describes this object std::string myDecName = dbInquire->getMyDecName(); int pos = (int)myDecName.find_last_of("/"); pos--; pos = (int)myDecName.find_last_of("/", pos); myDecName.erase(0,pos+1); // set config name to DBInquire's decorated name to allow automatc saving m_conf->m_confName = myDecName; } GPIBPixDcsChan::GPIBPixDcsChan(GPIBPixDcsChan &chan_in) : PixDcsChan(chan_in.m_parent, 0){ configInit(); *m_conf = *(chan_in.m_conf); } GPIBPixDcsChan::~GPIBPixDcsChan(){ // delete m_conf; // taken care of by PixDcs's config } void GPIBPixDcsChan::configInit(){ // Create the Config object m_conf = new Config("GPIBPixDcsChan"); Config &conf = *m_conf; // Group general conf.addGroup("general"); conf["general"].addString("ChannelName", m_name, "unknown", "name of PixDcs channel", true); conf["general"].addInt("ChannelID", m_channelID, -1, "ID of channel on this device", true); conf.addGroup("settings"); GPIBPixDcs* myDcs = dynamic_cast(m_parent); if(myDcs != 0 && myDcs->getDevType()==PixDcs::SUPPLY){ conf["settings"].addFloat("NomVolts", m_nomVolts, 0.0, "Nominal voltage (in V) on this channel", true); conf["settings"].addFloat("CurrLim", m_currLim, 0.0, "Current limit (in A) on this channel", true); conf["settings"].addInt("RampTime",m_rampTime, 1, "Time (in s) for ramping to full voltage", true); conf["settings"].addFloat("RampSteps",m_rampVoltSteps, 1, "Voltage-steps (in V) for ramping up/down", true); m_rtype = VCBOTH; // must never change this, so not in config! } else{ std::map rtlist; rtlist["VOLTS_ONLY"] = VONLY; rtlist["CURR_ONLY"] = CONLY; rtlist["VOLTS_AND_CURR"] = VCBOTH; conf["general" ].addList ("ReadType", (int &)m_rtype, VONLY, rtlist, "Type of reading for this meter/ADC-channel", true); conf["settings"].addBool ("AutoRange", m_autoRange, true, "Auomatic adjustment of measurement range (if supported)", true); conf["settings"].addFloat("MeasRange", m_measRange, 1.0, "Range of measurement (unless auto-range is active)", true); } conf.reset(); } double GPIBPixDcsChan::ReadParam(std::string measType) { // Read a string value from DDC, returning a double. GPIBPixDcs* myDcs = dynamic_cast(m_parent); double ret=0.0; if(measType=="voltage"){ if(m_rtype!=CONLY){ myDcs->m_gpibDev->measureVoltages(m_measRange, m_autoRange, m_channelID); if(m_channelID>=0 && m_channelID<(int)myDcs->m_gpibDev->getDeviceNumberChannels()) ret = (double)myDcs->m_gpibDev->getVoltage(m_channelID); } else throw PixDcsExc(PixDcsExc::ERROR, "request for voltage reading, but channel is current-reading only"); } else if(measType=="current"){ if(m_rtype!=VONLY){ myDcs->m_gpibDev->measureCurrents(m_measRange, m_autoRange, m_channelID); if(m_channelID>=0 && m_channelID<(int)myDcs->m_gpibDev->getDeviceNumberChannels()) ret = (double)myDcs->m_gpibDev->getCurrent(m_channelID); } else throw PixDcsExc(PixDcsExc::ERROR, "request for current reading, but channel is voltage-reading only"); } else throw PixDcsExc(PixDcsExc::ERROR, "request for neither voltage nor current: "+measType); return ret; } void GPIBPixDcsChan::SetParam(string varType) { // Set resource with string id to default value. if(varType=="voltage") SetParam(varType, (double)m_nomVolts); else if(varType=="currentlim") SetParam(varType, (double)m_currLim); else throw PixDcsExc(PixDcsExc::ERROR, "request for neither voltage nor current limit: "+varType); } void GPIBPixDcsChan::SetParam(string varType, double value) { // Set resource with string id to a double value. GPIBPixDcs* myDcs = dynamic_cast(m_parent); if(myDcs == 0) return; if(myDcs->m_gpibDev==0) return; // can't set anything without init. hardware if(myDcs->getDevType()!=PixDcs::SUPPLY) return; if(varType=="voltage"){ if(m_channelID>=0 && m_channelID<(int)myDcs->m_gpibDev->getDeviceNumberChannels()) myDcs->m_gpibDev->setVoltage(m_channelID, value); } else if(varType=="currentlim"){ if(m_channelID>=0 && m_channelID<(int)myDcs->m_gpibDev->getDeviceNumberChannels()) myDcs->m_gpibDev->setCurrentLimit(m_channelID, value); } else throw PixDcsExc(PixDcsExc::ERROR, "request for neither voltage nor current limit: "+varType); myDcs->m_gpibDev->measureVoltages(); myDcs->m_gpibDev->measureCurrents(); } std::string GPIBPixDcsChan::ReadState(std::string){ return "unknown"; } void GPIBPixDcsChan::SetState(std::string){ return; } GPIBPixDcs::GPIBPixDcs(DBInquire *dbInquire, void* )//interface) : PixDcs(dbInquire, 0){ m_gpibDev = 0; configInit(); m_conf->read(dbInquire); for(recordIterator it = dbInquire->recordBegin(); it != dbInquire->recordEnd(); it++){ // Look for DCS channel inquire if((*it)->getName() == "PixDcsChan") { GPIBPixDcsChan *gch = new GPIBPixDcsChan(this, *it); m_channels.push_back(gch); m_conf->addConfig(gch->m_conf); // set default name and channel ID if none given yet int chID = (int)m_channels.size()-1; std::stringstream a; a << chID; if(gch->m_name=="unknown"){ gch->m_name = m_name+"_Ch"+a.str(); gch->m_channelID = chID; } } } } GPIBPixDcs::~GPIBPixDcs(){ delete m_gpibDev; delete m_conf; } std::string GPIBPixDcs::ReadState(std::string) { // Read a string value from DDC, returning a string. std::string ret="uninit."; if(m_gpibDev!=0){ switch(m_gpibDev->getStatus()){ case PGD_ON: ret = "ON"; if(m_devType!=SUPPLY) ret = "OK"; // ON and OFF meaningless for meter break; case PGD_OFF: ret = "OFF"; if(m_devType!=SUPPLY) ret = "OK"; // ON and OFF meaningless for meter break; default: case PGD_ERROR: ret = "ERROR"; } } return ret; } void GPIBPixDcs::SetState(std::string new_state){ if(new_state!="OFF" && new_state!="ON") throw PixDcsExc(PixDcsExc::ERROR, "unknown request for change in state (should be ON or OFF): "+new_state); if(m_gpibDev==0) return; // can't set anything without init. hardware if(m_devType!=SUPPLY) return; // can only set this for supplies if(m_gpibDev->getStatus()==PGD_ON && new_state=="OFF"){ for(vector::iterator IT=m_channels.begin(); IT!=m_channels.end(); IT++){ GPIBPixDcsChan *chan = dynamic_cast(*IT); float in_volts = (float)chan->ReadParam("voltage"); float mysign=1; if(in_volts<0) mysign=-1; if(((int)chan->m_rampVoltSteps)!=0){ // avoids endless loops for(; (in_volts*mysign)>=0; in_volts-=mysign*fabs(chan->m_rampVoltSteps)){ chan->SetParam("voltage", in_volts); unsigned int ustime = (unsigned int) 1000*chan->m_rampTime; PixLib::sleep(ustime); } } chan->SetParam("voltage", 0.); } m_gpibDev->setState(PGD_OFF); return; } if(m_gpibDev->getStatus()==PGD_OFF && new_state=="ON"){ for(vector::iterator IT=m_channels.begin(); IT!=m_channels.end(); IT++){ GPIBPixDcsChan *chan = dynamic_cast(*IT); chan->SetParam("currentlim"); chan->SetParam("voltage", 0.); } m_gpibDev->setState(PGD_ON); for(vector::iterator IT=m_channels.begin(); IT!=m_channels.end(); IT++){ GPIBPixDcsChan *chan = dynamic_cast(*IT); float mysign=1; if(chan->m_nomVolts<0) mysign=-1; if(((int)chan->m_rampVoltSteps)!=0){ // avoids endless loops for(float in_volts = 0.; (in_volts*mysign)<=(mysign*chan->m_nomVolts); in_volts+=mysign*fabs(chan->m_rampVoltSteps)){ chan->SetParam("voltage", in_volts); unsigned int ustime = (unsigned int) 1000*chan->m_rampTime; PixLib::sleep(ustime); } } chan->SetParam("voltage", chan->m_nomVolts); } return; } if(m_gpibDev->getStatus()==PGD_ON && new_state=="ON"){ for(vector::iterator IT=m_channels.begin(); IT!=m_channels.end(); IT++){ GPIBPixDcsChan *chan = dynamic_cast(*IT); chan->SetParam("currentlim"); } for(vector::iterator IT=m_channels.begin(); IT!=m_channels.end(); IT++){ GPIBPixDcsChan *chan = dynamic_cast(*IT); float mysign=1; float curr_volt = chan->ReadParam("voltage"); if(chan->m_nomVoltsm_rampVoltSteps)!=0 && fabs(chan->m_nomVolts-curr_volt)>chan->m_rampVoltSteps){ // avoids endless loops and mistakes if difference between current // and wanted status is small for(float in_volts = curr_volt; (in_volts*mysign)<=(mysign*chan->m_nomVolts); in_volts+=mysign*fabs(chan->m_rampVoltSteps)){ chan->SetParam("voltage", in_volts); unsigned int ustime = (unsigned int) 1000*chan->m_rampTime; PixLib::sleep(ustime); } } chan->SetParam("voltage", chan->m_nomVolts); unsigned int ustime = (unsigned int) 1000*chan->m_rampTime; PixLib::sleep(ustime); } return; } } void GPIBPixDcs::configInit(){ // Create the Config object m_conf = new Config("GPIBPixDcs"); Config &conf = *m_conf; // Group general conf.addGroup("general"); conf["general"].addString("DeviceName", m_name, "unknown","name of PixDcs device", true); conf["general"].addInt("board_ID", m_boardID, 0, "ID of GPIB interface", true); conf["general"].addInt("GPIB_Chan", m_gpibChan, -1, "GPIB channel number of this device", true); conf["general"].addList("DeviceType", (int &)m_devType, SUPPLY, m_typeMap, "Type of device", false); conf["general"].addInt("Index", m_index, -1, "Index - order in which device is used amongst other DCS devices", true); conf.reset(); } void GPIBPixDcs::initHW(){ if(m_gpibDev==0){ m_gpibDev = new PixGPIBDevice(m_boardID, m_gpibChan, 0, (m_devType==PixDcs::ADCMETER)); } else{ SetState("OFF"); m_gpibDev->resetDevice(); } if(m_devType==SUPPLY){ for(vector::iterator IT=m_channels.begin(); IT!=m_channels.end(); IT++){ GPIBPixDcsChan *chan = dynamic_cast(*IT); chan->SetParam("currentlim"); } } } bool GPIBPixDcs::sendCommand(std::string &txt, bool readResp){ if(m_gpibDev==0) return false; char command[120], answer[120]; strncpy(command, txt.c_str(), 120); bool retval = m_gpibDev->writeDevice(command); if(readResp){ retval |= m_gpibDev->readDevice(answer); txt = answer; } return retval; }