/////////////////////////////////////////////////////////////////// // PixGPIBDevice.cxx // Implementation file for class PixGPIBDevice /////////////////////////////////////////////////////////////////// // (c) ATLAS Pixel Detector software /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // Version 00-00-01 21/11/2008 Daniel Dobos // Modified by Peyton Murray /////////////////////////////////////////////////////////////////// #include "PixGPIBDevice.h" #include "PixGPIBError.h" #include #include #include #include #include #include #include #ifdef WIN32 #include #else #include #endif #include "ni488.h" #define DEBUG false using namespace std; //////////////////////// // constructors //////////////////////// PixGPIBDevice::PixGPIBDevice(unsigned int board, unsigned int PAD, unsigned int SAD, bool forceMeter) { m_meterReadType = -1; m_Board = board; m_PAD = PAD; m_SAD = SAD; m_Device = ibdev(m_Board,m_PAD,m_SAD,T10s,1,0); updateDescription(); // the Keithleys can also be used as meter, so allow to change from HV to METER if(forceMeter && (m_DeviceType == KEITHLEY_2410 || m_DeviceType == KEITHLEY_2400)) m_DeviceFunction = METER; //2*measurement range is the compliance else updateDeviceFunction(); updateDeviceNumberChannels(); initializeDevice(); m_range = -999999999.; m_autoRange = true; m_activeChannel = -1; //measureVoltages(1,true,-1); //measureCurrents(1,true,-1); } //////////////////////// // destructor //////////////////////// PixGPIBDevice::~PixGPIBDevice() { // Keithleys as meter must be turned off if ((m_DeviceType == KEITHLEY_2410 || m_DeviceType == KEITHLEY_2400) && m_DeviceFunction == METER) { if(DEBUG) cout << "turning Keithley off" << endl; char command[120]; sprintf(command, "OUTP OFF"); writeDevice(command); #ifdef WIN32 Sleep(500); #else usleep(500000); #endif } ibclr(m_Device); if (ibsta & ERR) m_PixGPIBError.printGPIBError("* ibclr Error"); ibonl(m_Device, 0); if (ibsta & ERR) m_PixGPIBError.printGPIBError("* ibonl Error"); } //////////////////////// // getBoard() //////////////////////// unsigned int PixGPIBDevice::getBoard() { return m_Board; } //////////////////////// // getPAD() //////////////////////// unsigned int PixGPIBDevice::getPAD() { return m_PAD; } //////////////////////// // getSAD() //////////////////////// unsigned int PixGPIBDevice::getSAD() { return m_SAD; } //////////////////////// // getDevice() //////////////////////// unsigned int PixGPIBDevice::getDevice() { return m_SAD; } //////////////////////// // getDescription() //////////////////////// char * PixGPIBDevice::getDescription() { return m_Description; } //////////////////////// // updateDescription() //////////////////////// int PixGPIBDevice::updateDescription() { ibclr(m_Device); if (ibsta & ERR) { m_PixGPIBError.printGPIBError("* ibclr Error"); return 1; } char command[120]; sprintf(command,"*IDN?"); if (writeDevice(command)) return 1; ibrd(m_Device, m_Description, 120); if (ibsta & ERR) { m_PixGPIBError.printGPIBError("* ibrd Error"); return 1; } m_Description[ibcntl] = '\0'; string description = m_Description; if (strcmp((description.substr(0,23)).c_str(),"HEWLETT-PACKARD,E3631A,") == 0) m_DeviceType = AGILENT_3631A; else if (strcmp((description.substr(0,23)).c_str(),"HEWLETT-PACKARD,34401A,") == 0) m_DeviceType = HP_34401A; else if (strcmp((description.substr(0,28)).c_str(),"Agilent Technologies,E3642A,") == 0) m_DeviceType = AGILENT_E3642A; else if (strcmp((description.substr(0,28)).c_str(),"Agilent Technologies,E3644A,") == 0) m_DeviceType = AGILENT_E3644A; else if (strcmp((description.substr(0,23)).c_str(),"THURLBY-THANDAR,PL330DP") == 0) m_DeviceType = TTI_PL330DP; else if (strcmp((description.substr(0,23)).c_str(),"THURLBY-THANDAR,PL330TP") == 0) m_DeviceType = TTI_PL330TP; else if (strcmp((description.substr(0,25)).c_str(),"THURLBY THANDAR, PL303QMD") == 0) m_DeviceType = TTI_PL303QMD; else if (strcmp((description.substr(0,23)).c_str(),"THURLBY-THANDAR,QL355TP") == 0) m_DeviceType = TTI_QL355TP; else if (strcmp((description.substr(0,37)).c_str(),"KEITHLEY INSTRUMENTS INC.,MODEL 2410,") == 0) m_DeviceType = KEITHLEY_2410; else if (strcmp((description.substr(0,37)).c_str(),"KEITHLEY INSTRUMENTS INC.,MODEL 2400,") == 0) m_DeviceType = KEITHLEY_2400; else if (strcmp((description.substr(0,37)).c_str(),"KEITHLEY INSTRUMENTS INC.,MODEL 2000,") == 0) m_DeviceType = KEITHLEY_2000; else if (strcmp((description.substr(0,37)).c_str(),"KEITHLEY INSTRUMENTS INC.,MODEL 2001,") == 0) m_DeviceType = KEITHLEY_2001; else if (strcmp((description.substr(0,27)).c_str(),"Agilent Technologies,34410A") == 0) m_DeviceType = AGILENT_34410A; else if ((description.c_str()[0] == '+') || (description.c_str()[0] == '-')) //Special handling for the old timey Fluke 8842A commands. { #ifdef WIN32 Sleep(500); #else usleep(500000); #endif char answer[120]; sprintf(command, "G8"); if (writeDevice(command)) return 1; if (readDevice(answer)) return 1; description = answer; strcpy(m_Description, description.c_str()); if (strcmp((description.substr(0,11)).c_str(),"FLUKE,8842A") == 0) m_DeviceType = FLUKE_8842A; } else { if(DEBUG) cout << "unidentified description: " << description << endl; ibclr(m_Device); if (ibsta & ERR) { m_PixGPIBError.printGPIBError("* ibclr Error"); return 1; } sprintf(command,"U0X"); writeDevice(command); ibrd(m_Device, m_Description, 120); if (ibsta & ERR) { m_PixGPIBError.printGPIBError("* ibrd Error"); return 1; } m_Description[ibcntl] = '\0'; description = m_Description; if (strcmp((description.substr(0,3)).c_str(),"487") == 0) m_DeviceType = KEITHLEY_487; else m_DeviceType = UNKNOWN; } // check for the possible extension for this multimeter: a 10-channel mutliplexer if (m_DeviceType == KEITHLEY_2000 || m_DeviceType == KEITHLEY_2001) { char answer[120]; sprintf(command,"*OPT?"); if (writeDevice(command)) return 1; if (readDevice(answer)) return 1; if (strncmp(answer ,"0,2001-SCAN", 11) == 0 || strncmp(answer ,"0,200X-SCAN", 11) == 0) { if(m_DeviceType == KEITHLEY_2000) m_DeviceType = KEITHLEY_2000_SCANCARD; else m_DeviceType = KEITHLEY_2001_SCANCARD; } } return 0; } //////////////////////// // getDeviceType() //////////////////////// DeviceType PixGPIBDevice::getDeviceType() { return m_DeviceType; } //////////////////////// // getDeviceFunction() //////////////////////// DeviceFunction PixGPIBDevice::getDeviceFunction() { return m_DeviceFunction; } //////////////////////// // getDeviceNumberChannels() //////////////////////// unsigned int PixGPIBDevice::getDeviceNumberChannels() { return m_DeviceNumberChannels; } //////////////////////// // updateDeviceNumberChannels() //////////////////////// void PixGPIBDevice::updateDeviceNumberChannels() { if (m_DeviceType == AGILENT_3631A) m_DeviceNumberChannels = 3; else if (m_DeviceType == HP_34401A) m_DeviceNumberChannels = 1; else if (m_DeviceType == AGILENT_E3642A) m_DeviceNumberChannels = 1; else if (m_DeviceType == AGILENT_E3644A) m_DeviceNumberChannels = 1; else if (m_DeviceType == AGILENT_364xA1CH) m_DeviceNumberChannels = 1; else if (m_DeviceType == AGILENT_364xA2CH) m_DeviceNumberChannels = 2; else if (m_DeviceType == TTI_PL330DP) m_DeviceNumberChannels = 2; else if (m_DeviceType == TTI_PL330TP) m_DeviceNumberChannels = 3; else if (m_DeviceType == TTI_PL303QMD) m_DeviceNumberChannels = 2; else if (m_DeviceType == TTI_QL355TP) m_DeviceNumberChannels = 2; else if (m_DeviceType == KEITHLEY_237) m_DeviceNumberChannels = 1; else if (m_DeviceType == KEITHLEY_487) m_DeviceNumberChannels = 1; else if (m_DeviceType == KEITHLEY_2410) m_DeviceNumberChannels = 1; else if (m_DeviceType == KEITHLEY_2400) m_DeviceNumberChannels = 1; else if (m_DeviceType == KEITHLEY_2000) m_DeviceNumberChannels = 1; else if (m_DeviceType == KEITHLEY_2001) m_DeviceNumberChannels = 1; else if (m_DeviceType == KEITHLEY_2000_SCANCARD) m_DeviceNumberChannels = 10; else if (m_DeviceType == KEITHLEY_2001_SCANCARD) m_DeviceNumberChannels = 10; else if (m_DeviceType == AGILENT_34410A) m_DeviceNumberChannels = 1; else if (m_DeviceType == FLUKE_8842A) m_DeviceNumberChannels = 1; else m_DeviceNumberChannels = 0; } //////////////////////// // updateDeviceFunction() //////////////////////// void PixGPIBDevice::updateDeviceFunction() { if (m_DeviceType == AGILENT_3631A) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == HP_34401A) m_DeviceFunction = METER; else if (m_DeviceType == AGILENT_E3642A) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == AGILENT_E3644A) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == AGILENT_364xA1CH) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == AGILENT_364xA2CH) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == TTI_PL330DP) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == TTI_PL330TP) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == TTI_PL303QMD) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == TTI_QL355TP) m_DeviceFunction = LV_MODULE; else if (m_DeviceType == KEITHLEY_237) m_DeviceFunction = HV; else if (m_DeviceType == KEITHLEY_487) m_DeviceFunction = HV; else if (m_DeviceType == KEITHLEY_2410) m_DeviceFunction = HV; else if (m_DeviceType == KEITHLEY_2400) m_DeviceFunction = HV; else if (m_DeviceType == KEITHLEY_2000) m_DeviceFunction = METER; else if (m_DeviceType == KEITHLEY_2001) m_DeviceFunction = METER; else if (m_DeviceType == KEITHLEY_2000_SCANCARD) m_DeviceFunction = METER; else if (m_DeviceType == KEITHLEY_2001_SCANCARD) m_DeviceFunction = METER; else if (m_DeviceType == AGILENT_34410A) m_DeviceFunction = METER; else if (m_DeviceType == FLUKE_8842A) m_DeviceFunction = METER; else m_DeviceFunction = NONE; } //////////////////////// // getStatus() //////////////////////// DeviceStatus PixGPIBDevice::getStatus() { return m_Status; } //////////////////////// // initializeDevice() //////////////////////// int PixGPIBDevice::initializeDevice() { // send status request command char command[120]; // spercial dirty trick for "old" TTi PL330's and QL355's since there is no on/off status information if (m_DeviceType == TTI_PL330DP || m_DeviceType == TTI_PL330TP || m_DeviceType == TTI_QL355TP) { // check voltage on channel 1 sprintf(command, "V1O?"); if (writeDevice(command)) return 1; char answer[120]; if (readDevice(answer)) return 1; answer[ibcntl] = '\0'; if(DEBUG) cout << "DEBUG : TTi volt request - answer: " << answer << endl; float volts = atof(answer); if(fabs(volts)<1e-2) { // setting is zero volts - check if this can be changed // if yes, status is on, if not, status is off // set de-/incremental delta sprintf(command, "DELTAV1 0.1"); if (writeDevice(command)) return 1; // increment voltage sprintf(command, "INCV1"); if(DEBUG) cout << "DEBUG : executing command " << command << endl; if (writeDevice(command)) return 1; #ifdef WIN32 Sleep(500); #else usleep(500000); #endif // read back and check for change sprintf(command, "V1O?"); if (writeDevice(command)) return 1; answer[0] ='\0'; if (readDevice(answer)) return 1; answer[ibcntl] = '\0'; if(DEBUG) cout << "DEBUG : TTi increm. volt request - answer: " << answer << endl; // return to original value sprintf(command, "DECV1"); if (writeDevice(command)) return 1; volts = atof(answer); if(fabs(volts)<0.03) { m_Status = PGD_OFF ; return 0; } else { m_Status = PGD_ON ; return 0; } } else { m_Status = PGD_ON ; return 0; } } if (m_DeviceType == KEITHLEY_237) sprintf(command, "U3X"); else if (m_DeviceType == KEITHLEY_487) sprintf(command, "U0X"); // NB: since we're only using OPALL, it should be OK to check just channel 1, channel 2 must be identical else if (m_DeviceType == TTI_PL303QMD) sprintf(command, "OP1?"); else if((m_DeviceType == KEITHLEY_2410 || m_DeviceType == KEITHLEY_2400) && m_DeviceFunction == METER) { sprintf(command, ":SOUR:VOLT 0"); //to protect DUT if (writeDevice(command)) return 1; sprintf(command, ":SOUR:VOLT:RANG MIN"); //to protect DUT if (writeDevice(command)) return 1; sprintf(command, ":SOUR:CURR 0"); if (writeDevice(command)) return 1; sprintf(command, ":SOUR:CURR:RANG MIN"); //to protect DUT if (writeDevice(command)) return 1; m_Status = PGD_ON ; return 0; } else if(m_DeviceType == KEITHLEY_2000 || m_DeviceType == KEITHLEY_2001) { m_Status = PGD_ON ; sprintf(command, "*RST"); if (writeDevice(command)) return 1; return 0; } else if(m_DeviceType == KEITHLEY_2000_SCANCARD || m_DeviceType == KEITHLEY_2001_SCANCARD) { m_Status = PGD_ON ; sprintf(command, "*RST"); if (writeDevice(command)) return 1; sprintf(command, "ROUTE:OPEN:ALL"); if (writeDevice(command)) return 1; return 0; } else if(m_DeviceType == AGILENT_34410A) // nothing to do for Agilent meter { m_Status = PGD_ON ; return 0; } else if (m_DeviceType == AGILENT_E3642A)//Nothing to do for agilent meter. { m_Status = PGD_OFF ; //If you turn it on right away, it behaves weirdly until you turn it on and off a few times in STControl. return 0; } else if (m_DeviceType == AGILENT_E3644A) { m_Status = PGD_OFF ; //If you turn it on right away, it behaves weirdly until you turn it on and off a few times in STControl. return 0; } else if (m_DeviceType == HP_34401A) { m_Status = PGD_ON ; sprintf(command, "*RST"); if (writeDevice(command)) return 1; return 0; } else if (m_DeviceType == FLUKE_8842A) { m_Status = PGD_ON; sprintf(command, "* S1"); if (writeDevice(command)) return 1; return 0; } else { sprintf(command, "OUTP:STAT?"); } if (writeDevice(command)) return 1; //Possibly not necessary, and maybe even a bug // receive status request answer and set m_Status char answer[120]; if (readDevice(answer)) return 1; answer[ibcntl] = '\0'; if(DEBUG) cout << "DEBUG : initialize - answer: " << answer << endl; int status; if (m_DeviceType == KEITHLEY_237) status = (int)answer[19] - 48; else if (m_DeviceType == KEITHLEY_487) status = (int)answer[29] - 48; else status = atoi(answer); if (status == 1) m_Status = PGD_ON; else if (status == 0) m_Status = PGD_OFF; else m_Status = PGD_ERROR; if(m_DeviceType == KEITHLEY_2410){ sprintf(command,":SOUR:VOLT:RANG 1000"); if (writeDevice(command)) return 1; sprintf(command,":SENS:CURR:RANG:AUTO ON"); if (writeDevice(command)) return 1; sprintf(command,":SENS:VOLT:RANG:AUTO ON"); if (writeDevice(command)) return 1; } if(m_DeviceType == KEITHLEY_2400){ sprintf(command,":SOUR:VOLT:RANG 200"); if (writeDevice(command)) return 1; sprintf(command,":SENS:CURR:RANG:AUTO ON"); if (writeDevice(command)) return 1; sprintf(command,":SENS:VOLT:RANG:AUTO ON"); if (writeDevice(command)) return 1; } return 0; } void PixGPIBDevice::setState(DeviceStatus state) { if (m_DeviceType != KEITHLEY_2410) { if(state!=PGD_ON && state!=PGD_OFF) return; if(m_DeviceFunction == METER) return; } char command[120]; switch(m_DeviceType) { case TTI_PL330DP: case TTI_PL330TP: case TTI_PL303QMD: case TTI_QL355TP: sprintf(command, (state==PGD_ON)?"OPALL 1":"OPALL 0"); break; case AGILENT_3631A: case AGILENT_E3642A: case AGILENT_E3644A: case KEITHLEY_2410: case KEITHLEY_2400: case KEITHLEY_2000: case KEITHLEY_2001: sprintf(command, (state==PGD_ON)?"OUTP ON":"OUTP OFF"); break; case KEITHLEY_2000_SCANCARD: //Should be meters anyway, but I add them here just in case. case KEITHLEY_2001_SCANCARD: case FLUKE_8842A: case HP_34401A: default: // do nothing return; } if (writeDevice(command)) return; m_Status = state; } void PixGPIBDevice::setVoltage(unsigned int channel, double voltage) { char command[120]; if(channel<0 || channel>=m_DeviceNumberChannels) return; if(m_DeviceFunction == METER) return; switch(m_DeviceType) { case TTI_PL330DP: case TTI_PL330TP: case TTI_PL303QMD: case TTI_QL355TP: sprintf(command,"V%d %f",(channel+1), (float)voltage); break; case KEITHLEY_2410: case KEITHLEY_2400: sprintf(command,":SOUR:VOLT %f",(float)voltage); break; case AGILENT_3631A: // select requested channel first sprintf(command,"INST:NSEL %d", channel+1); if (writeDevice(command)) return; // then send setting command sprintf(command,"VOLT %f", (float)voltage); break; case AGILENT_E3642A: case AGILENT_E3644A: sprintf(command,"VOLT %f", (float)voltage); break; default: // do nothing return; } if (writeDevice(command)) return; } void PixGPIBDevice::setCurrentLimit(unsigned int channel, double current) { char command[120]; if(channel<0 || channel>=m_DeviceNumberChannels) return; if(m_DeviceFunction == METER) return; switch(m_DeviceType) { case TTI_PL330DP: case TTI_PL330TP: case TTI_PL303QMD: case TTI_QL355TP: sprintf(command,"I%d %f",(channel+1),(float)current); break; case KEITHLEY_2410: case KEITHLEY_2400: { sprintf(command,":SENS:CURR:PROT %de-7",(int)(current*1e7+.01)); break; } case AGILENT_3631A: // select requested channel first if(channel==0) sprintf(command,"INST:SEL P6V"); if(channel==1) sprintf(command,"INST:SEL P25V"); if(channel==2) sprintf(command,"INST:SEL N25V"); if (writeDevice(command)) return; // then send setting command sprintf(command,"CURR %f", (float)current); break; case AGILENT_E3642A: case AGILENT_E3644A: sprintf(command,"CURR %f", (float)current); break; default: // do nothing return; } if(DEBUG) cout << "DEBUG : setting current limit to " << current << " with command "<< command << endl; if (writeDevice(command)) return; } //////////////////////// // measureVoltages() //////////////////////// int PixGPIBDevice::measureVoltages(float inRange, bool inAutoRange, int pChannel) { int tStatus = 0; if (pChannel < 0) { for (unsigned int iChannel = 0; iChannel < m_DeviceNumberChannels; ++iChannel) // loop over all channels { if (measureVoltage(inRange, inAutoRange, iChannel) < 1) tStatus = -1; } } else tStatus = measureVoltage(inRange, inAutoRange, pChannel); // just take one channel return tStatus; } //////////////////////// // measureCurrents() //////////////////////// int PixGPIBDevice::measureCurrents(float inRange, bool inAutoRange, int pChannel) { int tStatus = 0; if (pChannel < 0) { for (unsigned int iChannel = 0; iChannel < m_DeviceNumberChannels; ++iChannel) // loop over all channels { if (measureCurrent(inRange, inAutoRange, iChannel) < 1) tStatus = -1; } } else tStatus = measureCurrent(inRange, inAutoRange, pChannel); // just take one channel return tStatus; } //////////////////////// // measureVoltage() //////////////////////// int PixGPIBDevice::measureVoltage(float inRange, bool inAutoRange, int pChannel) { if (pChannel < 0 || pChannel > m_DeviceNumberChannels-1) return -1; char command[120]; // send voltage measurement request command if (m_DeviceType == AGILENT_3631A) { if (pChannel == 0) sprintf(command, "MEAS:VOLT? P6V"); else if (pChannel == 1) sprintf(command, "MEAS:VOLT? P25V"); else if (pChannel == 2) sprintf(command, "MEAS:VOLT? N25V"); } else if (m_DeviceType == AGILENT_E3642A) { sprintf(command, "MEAS:VOLT?"); } else if (m_DeviceType == AGILENT_E3644A) { sprintf(command, "MEAS:VOLT?"); } else if(m_DeviceType == AGILENT_34410A) { if(m_meterReadType!=0 || inRange!=m_range || inAutoRange!=m_autoRange) { m_range = inRange; m_autoRange = inAutoRange; if(m_autoRange) sprintf(command, "CONF:VOLT:DC AUTO"); else sprintf(command, "CONF:VOLT:DC %.0e",m_range); if (writeDevice(command)) return 1; m_meterReadType = 0; } if (pChannel == 0) sprintf(command, "READ?"); } else if (m_DeviceType == AGILENT_364xA1CH) { if (pChannel == 0) sprintf(command, "MEAS:VOLT?"); } else if (m_DeviceType == AGILENT_364xA2CH) { if (pChannel == 0) { sprintf(command, "INST:SEL OUT1"); if (writeDevice(command)) return 1; sprintf(command, "MEAS:VOLT?"); } else if (pChannel == 1) { sprintf(command, "INST:SEL OUT2"); if (writeDevice(command)) return 1; sprintf(command, "MEAS:VOLT?"); } } else if (m_DeviceType == TTI_PL330DP || m_DeviceType == TTI_PL303QMD || m_DeviceType == TTI_PL330TP || m_DeviceType == TTI_QL355TP) { sprintf(command, "V%dO?", (pChannel+1)); } else if (m_DeviceType == KEITHLEY_237) { if (pChannel == 0) sprintf(command, "G1,2,0H0X"); } else if (m_DeviceType == KEITHLEY_487) { if (pChannel == 0) sprintf(command, "U8X"); } else if (m_DeviceType == KEITHLEY_2410 || m_DeviceType == KEITHLEY_2400) { if (pChannel == 0) { if(m_DeviceFunction == METER) { if(m_meterReadType!=0 || inRange!=m_range || inAutoRange!=m_autoRange) { m_range = inRange; m_autoRange = inAutoRange; sprintf(command, "OUTP OFF"); if (writeDevice(command)) return 1; sprintf(command, ":SOUR:FUNC CURR"); if (writeDevice(command)) return 1; sprintf(command, ":SOUR:CURR 0"); if (writeDevice(command)) return 1; sprintf(command, ":SENS:FUNC \"VOLT\""); if (writeDevice(command)) return 1; sprintf(command, ":SENS:VOLT:PROT %.0e",2.f*inRange); if (writeDevice(command)) return 1; sprintf(command, ":SENS:VOLT:RANG %.0e",inRange); if (writeDevice(command)) return 1; sprintf(command, "OUTP ON"); if (writeDevice(command)) return 1; m_meterReadType = 0; } sprintf(command, ":READ?"); } else sprintf(command, ":SOUR:VOLT:LEV:IMM:AMPL?"); } } else if (m_DeviceType == KEITHLEY_2000 || m_DeviceType == KEITHLEY_2001) { if (pChannel == 0 && m_DeviceFunction == METER) { if(m_meterReadType!=0 || inRange!=m_range || inAutoRange!=m_autoRange) { sprintf(command, ":SENS:FUNC 'VOLT:DC'"); if (writeDevice(command)) return 1; sprintf(command, ":SENS:VOLT:RANG %.0e",inRange); if (writeDevice(command)) return 1; sprintf(command, ":SENS:VOLT:RANG:AUTO %s", inAutoRange?"ON":"OFF"); if (writeDevice(command)) return 1; sprintf(command, ":READ?"); m_meterReadType = 0; } } } else if (m_DeviceType == KEITHLEY_2000_SCANCARD || m_DeviceType == KEITHLEY_2001_SCANCARD) { if (m_DeviceFunction == METER) { if(inRange!=m_range) { sprintf(command, ":SENS:VOLT:RANG %.0e",inRange); if (writeDevice(command)) return 1; m_range = inRange; } if(inAutoRange!=m_autoRange) { sprintf(command, ":SENS:VOLT:RANG:AUTO %s", inAutoRange?"ON":"OFF"); if (writeDevice(command)) return 1; m_autoRange = inAutoRange; } if(m_meterReadType!=0) { sprintf(command, ":SENS:FUNC 'VOLT:DC'"); if (writeDevice(command)) return 1; m_meterReadType = 0; } if((m_activeChannel != pChannel) && (m_DeviceType != KEITHLEY_2000_SCANCARD)) { char tChannelList[30] = "@"; for (int ichannel = 0; ichannel m_DeviceNumberChannels-1) return -1; if (m_Status == PGD_OFF) { if(DEBUG) cout << "DEBUG : device is off, printing default current of 0 " << endl; for (int pChannel = 0; pChannel < 3; pChannel++) { m_Currents[pChannel] = 0.0; } return 1; } if(DEBUG) cout << "DEBUG : checking current of channel " << pChannel << endl; // send current measurement request command char command[120]; if (m_DeviceType == AGILENT_3631A) { if (pChannel == 0) sprintf(command, "MEAS:CURR? P6V"); else if (pChannel == 1) sprintf(command, "MEAS:CURR? P25V"); else if (pChannel == 2) sprintf(command, "MEAS:CURR? N25V"); } else if (m_DeviceType == AGILENT_E3642A) { sprintf(command, "MEAS:CURR?"); } else if (m_DeviceType == AGILENT_E3644A) { sprintf(command, "MEAS:CURR?"); } else if(m_DeviceType == AGILENT_34410A) { if(m_meterReadType!=1 || inRange!=m_range || inAutoRange!=m_autoRange) { m_range = inRange; m_autoRange = inAutoRange; if(m_autoRange) sprintf(command, "CONF:CURR:DC AUTO"); else sprintf(command, "CONF:CURR:DC %.0e",m_range); if (writeDevice(command)) return 1; m_meterReadType = 1; } if (pChannel == 0) sprintf(command, "READ?"); } else if (m_DeviceType == AGILENT_364xA1CH) { if (pChannel == 0) sprintf(command, "MEAS:CURR?"); } else if (m_DeviceType == AGILENT_364xA2CH) { if (pChannel == 0) { sprintf(command, "INST:SEL OUT1"); if (writeDevice(command)) return 1; sprintf(command, "MEAS:CURR?"); } else if (pChannel == 1) { sprintf(command, "INST:SEL OUT2"); if (writeDevice(command)) return 1; sprintf(command, "MEAS:CURR?"); } } else if (m_DeviceType == TTI_PL330DP || m_DeviceType == TTI_PL303QMD || m_DeviceType == TTI_PL330TP || m_DeviceType == TTI_QL355TP) { sprintf(command, "I%dO?", (pChannel+1)); } else if (m_DeviceType == KEITHLEY_237) { if (pChannel == 0) sprintf(command, "G4,2,0H0X"); } else if (m_DeviceType == KEITHLEY_487) { if (pChannel == 0) sprintf(command, "G0B0X"); } else if (m_DeviceType == KEITHLEY_2410 || m_DeviceType == KEITHLEY_2400) { if (pChannel == 0) { if(m_DeviceFunction == METER) { if(inRange!=m_range) { sprintf(command, ":SENS:CURR:PROT %.0e", 2.f*inRange); ibwrt(m_Device, command, strlen(command)); if (writeDevice(command)) return 1; sprintf(command, ":SENS:CURR:RANG %.0e",inRange); if (writeDevice(command)) return 1; m_range = inRange; } if(inAutoRange!=m_autoRange) { sprintf(command, ":SENS:CURR:RANG:AUTO %s", inAutoRange?"ON":"OFF"); if (writeDevice(command)) return 1; m_autoRange = inAutoRange; } if(m_meterReadType!=1) { sprintf(command, "OUTP OFF"); if (writeDevice(command)) return 1; sprintf(command, ":SOUR:FUNC VOLT"); ibwrt(m_Device, command, strlen(command)); if (writeDevice(command)) return 1; sprintf(command, ":SOUR:VOLT 0"); ibwrt(m_Device, command, strlen(command)); if (writeDevice(command)) return 1; sprintf(command, ":SENS:FUNC \"CURR\""); if (writeDevice(command)) return 1; sprintf(command, "OUTP ON"); if (writeDevice(command)) return 1; m_meterReadType = 1; } } sprintf(command, ":READ?"); } } else if (m_DeviceType == KEITHLEY_2000 || m_DeviceType == KEITHLEY_2001) { if (pChannel == 0 && m_DeviceFunction == METER) { if(m_meterReadType != 0 || inRange != m_range || inAutoRange != m_autoRange) { m_range = inRange; m_autoRange = inAutoRange; sprintf(command, ":SENS:FUNC 'CURR:DC'"); if (writeDevice(command)) return 1; sprintf(command, ":SENS:CURR:RANG %.0e",inRange); if (writeDevice(command)) return 1; sprintf(command, ":SENS:CURR:RANG:AUTO %s", inAutoRange?"ON":"OFF"); if (writeDevice(command)) return 1; sprintf(command, ":READ?"); m_meterReadType = 1; } } } else if (m_DeviceType == KEITHLEY_2000_SCANCARD || m_DeviceType == KEITHLEY_2001_SCANCARD) { if (m_DeviceFunction == METER) { sprintf(command, ":ROUT:OPEN:ALL"); //disconnected all channels from the multimeter if (writeDevice(command)) return 1; //not supported, only via voltage drop over a resistor the current can be measured with a Keithley 200X + scan card } } else if (m_DeviceType == HP_34401A) { sprintf(command, "MEAS:CURR:DC?"); } else if (m_DeviceType == FLUKE_8842A) { sprintf(command, "F5 ?"); //Tells the Fluke to switch to mADC mode and take a measurement. } if (strlen(command) == 0) { m_Currents[pChannel] = 0.0; return 0; } if (writeDevice(command)) return 1; //sends read command // receive current measurement answer and set m_Currents char answer[120]; if (readDevice(answer)) return 1; answer[ibcntl] = '\0'; if(DEBUG) cout << "DEBUG : measureCurrents, Ch: " << pChannel << " - answer: " << answer; if (m_DeviceType == KEITHLEY_487) m_Currents[pChannel] = atof(&answer[4]); else if (m_DeviceType == KEITHLEY_2410 || m_DeviceType == KEITHLEY_2400 || m_DeviceType == KEITHLEY_2000 || m_DeviceType == KEITHLEY_2001 || m_DeviceType == KEITHLEY_2000_SCANCARD || m_DeviceType == KEITHLEY_2001_SCANCARD) { // extract second part of comma-separated list of measurements string sanswer = answer; int pos = (int)sanswer.find(","); if(pos!=(int)string::npos) sanswer.erase(0, pos+1); pos = (int)sanswer.find(","); if(pos!=(int)string::npos) sanswer.erase(pos, sanswer.length()-pos); m_Currents[pChannel] = atof(sanswer.c_str()); } else m_Currents[pChannel] = atof(answer); if ((m_DeviceType == KEITHLEY_2410 || m_DeviceType == KEITHLEY_2400) && m_DeviceFunction != METER) { sprintf(command, "*CLS"); if (writeDevice(command)) return 1; } return 0; } //////////////////////// // getCurrent() //////////////////////// float PixGPIBDevice::getCurrent(unsigned int pChannel) { return m_Currents[pChannel]; } void PixGPIBDevice::resetDevice() { ibclr(m_Device); if (ibsta & ERR) m_PixGPIBError.printGPIBError("* ibclr Error"); char command[120]; switch(m_DeviceType) { default: sprintf(command,"*RST"); } if (writeDevice(command)) return; initializeDevice(); } bool PixGPIBDevice::writeDevice(char (&command)[120]) { if (DEBUG) cout<<"command: "<