Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

viReadSTB hanging with Keithley 2110 over USB connection

Hello everyone,

I'm developing an application that needs to communicate with the multimeter Keithley 2110.

I installed the latest Keithely IO Library (KIOL-850C07), which bundles the NIVISA run-time version 5.2.

Everything works as expected: I can connect to the device, retrieve its ID, read voltage measurements and so on. However, once in a while voltage reading method gets stuck in the call to viReadSTB for about 120s before returning a VI_ERROR_SYSTEM_ERROR. I tried to read the timeout value:

ViUInt32 attrValue;
status = viGetAttribute(vi, VI_ATTR_TMO_VALUE, (void *)&attrValue);

which correctly returns the default value of 2000ms (much smaller than the actual wait time of 120000ms).

Trying to set a different timeout:

ViUInt32 attrValue = 1000;
status = viSetAttribute(vi, VI_ATTR_TMO_VALUE, attrValue);

does not make any difference.

I tried so to update the nivisa runtime to the latest available version (17.0). I did not update the visa.h and visa32.lib since visa.h has only minimal changes, while .lib is byte-to-byte unchanged.

Interestingly, all the above is true on a win10 machine, but if I run the very same application with the same libraries, drivers and device on a win7 machine (tried 2 of them) the hanging time reduces to 10s. Also in the latter case this time is unaffected by timeout setting.

 

I wanted to know what is causing the hang and if I can do anything to reduce the waiting time or get rid of it if possible.

I'm building the application using gcc 5.3.0.

 

Here below is the code snippet I'm using to communicate with the multimeter.

 

DMM.h

#ifndef DMM_H
#define DMM_H

#include <QObject>
#include <QThread>

#include "visa.h"

#define MANUFACTURER_ID 0x05E6 //Keithley
#define DMM_MODEL 0x2110 //Keithley 2110 5 1/2 Digit Multimeter

class Dmm : public QObject {
    Q_OBJECT

public:
    Dmm();
    ~Dmm();

    bool openConnection(int SerialNumber);
    bool closeConnection();
    bool identify(QString &identificationString);
    bool measureVoltage(double &value);
    bool clearErrors();

private:
    ViSession   defaultRM, vi; //these are pointers
    char        buf [256]   = {0};
    ViStatus    error       = VI_SUCCESS;
    ViUInt16    status      = 0;

signals:
    void errorMessage(QString);

public slots:
    bool initialize();
};

#endif // DMM_H

DMM.cpp

#include <stdio.h>
#include "DMM.h"
#include <windows.h>

Dmm::Dmm() {

}

Dmm::~Dmm() {

}

bool Dmm::openConnection(int SerialNumber) {
    char AddressString[60];
    int ManufacturerID  = MANUFACTURER_ID;
    int DMMmodel        = DMM_MODEL;
    
    sprintf(AddressString, "USB0::0x%x::0x%x::%d::INSTR", ManufacturerID, DMMmodel, SerialNumber);
    
    /*! Open session to USB device*/
    if ((error = viOpenDefaultRM(&defaultRM)) != VI_SUCCESS) {
        emit errorMessage("DMM: viOpenDefaultRM(&defaultRM) failed");
        return false;
    }

    if ((error = viOpen(defaultRM, AddressString, VI_NULL, VI_NULL, &vi)) != VI_SUCCESS) {
        emit errorMessage("DMM: viOpen(defaultRM, " + QString::fromUtf8(AddressString) + ", VI_NULL,VI_NULL, &vi) failed");
        return false;
    }

    return true;
}

bool Dmm::closeConnection() {
    /*! Restore DMM manual mode *!
    if ((error = viPrintf(vi, ":SYSTem:LOCal\n")) != VI_SUCCESS) {
        emit errorMessage("DMM: viPrintf(vi, \":SYSTem:LOCal\\n\")) failed");
        return false;
    }
    
    /* Close session */
    if ((error = viClose(vi)) != VI_SUCCESS) {
        emit errorMessage("DMM: DMM viClose(vi) failed");
        return false;
    }

    if ((error = viClose(defaultRM)) != VI_SUCCESS) {
        emit errorMessage("DMM: DMM viClose(defaultRM) failed");
        return false;
    }
    
    return true;
}

bool Dmm::clearErrors() {
    /*! Clears tester errors */
    if ((error = viPrintf(vi, "*CLS\n")) != VI_SUCCESS) {
        emit errorMessage("DMM: viPrintf(vi, \"*CLS\\n\") failed");
        return false;
    }

    return true;
}

bool Dmm::initialize() {
    /*! Resets the device to power on configuration */
    if ((error = viPrintf(vi, "*RST\n")) != VI_SUCCESS) {
        emit errorMessage("DMM: viPrintf(vi, \"*RST\\n\") failed");
        return false;
    }
    
    /*! Modify timeout */
    ViUInt32 attrValue = 1000;
    status = viSetAttribute(vi, VI_ATTR_TMO_VALUE, attrValue);

    /*! Clear error queue */
    return this->clearErrors();
}

bool Dmm::identify(QString &identificationString) {
    /*! Send an *IDN? string to the device */
    if ((error = viPrintf(vi, "*IDN?\n")) != VI_SUCCESS) {
        emit errorMessage("DMM: viPrintf(vi, \"*IDN?\\n\") failed");
        return false;
    }
    
    do {
        if ((error = viReadSTB(vi, &status)) != VI_SUCCESS) {
            emit errorMessage("DMM: viReadSTB(vi, &status) failed");
            return false;
        }
    } while (status == 0); //waits for 0x10, Message available (?)
    
    /*! Read results */
    if ((error = viScanf(vi, "%t", &buf)) != VI_SUCCESS) {
        emit errorMessage("DMM: viScanf(vi, \"%t\", &buf) failed");
        return false;
    }    
    
    identificationString = QString::fromUtf8(buf);
    return true;
}

bool Dmm::measureVoltage(double &value) {
    if ((error = viPrintf(vi, ":MEASure:VoltAge:DC?\n")) != VI_SUCCESS) {
        emit errorMessage("DMM: viPrintf(vi, \":MEASure:VoltAge:DC?\\n\") failed");
        return false;
    }

    /*! Wait 100ms to avoid too frequent calls */
    QThread::msleep(100);

    do {
        if ((error = viReadSTB(vi, &status)) != VI_SUCCESS) {
            emit errorMessage("DMM: viReadSTB(vi, &status) failed");
            this->initialize();
            return false;
        }
    } while (status == 0); //waits for 0x10, Message available (?)
    
    /*! Check that the data available bit is set, otherwise reset device and return */
    if (!(status & 0x10)) {
        this->initialize();
        return false;
    }

    /*! Read results */
    if ((error = viScanf(vi, "%t", &buf)) != VI_SUCCESS) {
        emit errorMessage("DMM: viScanf(vi, \"%t\", &buf) failed");
        return false;
    }

    sscanf(buf, "%lf", &value); /*!< returns a measure in volts */

    return true;
}

 

 

Thank you in advance for any help.

Best regards

0 Kudos
Message 1 of 9
(4,096 Views)

It sounds like a hardware issue for Tektronix/Keithley to look into since its exceeding the timeout, which shouldn't occur.

 

I'd check the Tektronix/Keithley website to make sure you have the most recent firmware update, the issue might have already been addressed in a newer firmware release.

 

Craig  

 

 

0 Kudos
Message 2 of 9
(4,071 Views)

Hi Craig,

Thanks for your reply!

How would you explain the fact that the same multimeter behaves differently when communicating with different PCs if it were a firmware issue?

I mean, it consistently waits 120s (not roughly 2 minutes, exactly 120 seconds all the times) when communicating with my win10 machine and it waits 10s (really very consistently in this case too) when communicating with the other 2 win7 machines I've tried.

 

Best regards,

 

Filippo

0 Kudos
Message 3 of 9
(4,067 Views)

I dunno, but in both cases you set the timeout to 2s so 10s and 120s not behaving well. 

 

I just noticed the K2110 is USB interface.  I've had USB problems when the power settings on the machine were not set to 

1) High Performance (Always ON)

2) Disabling the USB low power selective suspend.  See - https://www.windowscentral.com/how-prevent-windows-10-turning-usb-devices

 

USB selective suspend is nasty.  It allows the OS to essentially turn-off and forget about USB ports to save power.  The USB selective suspend on Win10 seems more aggressive that on Win7, and that might explain the longer delay times.  

 

If you are collecting data over USB and selective suspend occurs because you haven't communicated in few seconds it just forgets the connection.  In my case this caused programs to hang, in your case perhaps you just get long delays. 

 

I'd still see if there's a firmware update, and talk to Keithley who might have heard from other users with the same issues.

 

Craig

0 Kudos
Message 4 of 9
(4,064 Views)

This really seems worth a try, thank you very much for the hint!

I'll let you know if I can work this out.

 

Best regards,

 

Filippo

0 Kudos
Message 5 of 9
(4,062 Views)

Hello everyone,

I tried using the Power Settings as suggested by Craig but unfortunately it has not solved my problem.

I'll try contacting Keithley support and see if mine is a known issue.

 

Best regards,

 

Filippo

0 Kudos
Message 6 of 9
(4,044 Views)

Hello everyone,

Currently I have the same problem, can someone solve this problem?

 

Best regards.

0 Kudos
Message 7 of 9
(1,477 Views)

I also face the same issue with all the three Keithley 2110 DMMs.

0 Kudos
Message 8 of 9
(1,081 Views)

Does the Keithley/Tektronix I0 library really use NI-VISA 5.2?

That would be prehistoric and definitely long before anyone ever knew that Microsoft is going to release Windows 10 some day.

5.3 was the first to officially support Windows 8, 14.0 supported Windows 8.1 and 15.0 added support for Windows 10.

Rolf Kalbermatter
My Blog
0 Kudos
Message 9 of 9
(1,056 Views)